• 面试题学习总结--四


    1.Java.util.concurrent包下的类:参考自(https://blog.csdn.net/axi295309066/article/details/65665090

      1.1阻塞队列BolockingQueue

      BlockingQueue 通常用于一个线程生产对象,而另外一个线程消费这些对象的场景。下图是对这个原理的阐述:

    blocking-queue

    •   一个线程往里边放,另外一个线程从里边取的一个 BlockingQueue。
    •   一个线程将会持续生产新对象并将其插入到队列之中,直到队列达到它所能容纳的临界点。也就是说,它是有限的。如果该阻塞队列到达了其临界点,负责生产的线程将会在往里边插入新对象时发  生阻塞。它会一直处于阻塞之中,直到负责消费的线程从队列中拿走一个对象。
    •   负责消费的线程将会一直从该阻塞队列中拿出对象。如果消费线程尝试去从一个空的队列中提取对象的话,这个消费线程将会处于阻塞之中,直到一个生产线程把一个对象丢进队列。

    2.并发Map: ConcurrentMap

     ConcurrentHashMap

      2.1 ConcurrentHashMap 和 java.util.HashTable 类很相似,但 ConcurrentHashMap 能够提供比 HashTable 更好的并发性能。在你从中读取对象的时候 ConcurrentHashMap 并不会把整个 Map 锁住。此外,  在你向其中写入对象的时候,ConcurrentHashMap 也不会锁住整个 Map。它的内部只是把 Map 中正在被写入的部分进行锁定。

      2.2 另外一个不同点是,在被遍历的时候,即使是 ConcurrentHashMap 被改动,它也不会抛ConcurrentModificationException。尽管 Iterator 的设计不是为多个线程的同时使用。

    3.信号量 Semaphore

      3.1 java.util.concurrent.Semaphore 类是一个计数信号量。这就意味着它具备两个主要方法:acquire(); release()

      3.2 计数信号量由一个指定数量的 “许可” 初始化。每调用一次 acquire(),一个许可会被调用线程取走。每调用一次 release(),一个许可会被返还给信号量。因此,在没有任何 release() 调用时,最多有 N 个线  程能够通过 acquire() 方法,N 是该信号量初始化时的许可的指定数量。这些许可只是一个简单的计数器。这里没啥奇特的地方。

      3.3 信号量主要有两种用途:

    • 保护一个重要(代码)部分防止一次超过 N 个线程进入
    • 在两个线程之间发送信号

      3.4 公平性

        没有办法保证线程能够公平地可从信号量中获得许可。也就是说,无法担保掉第一个调用 acquire() 的线程会是第一个获得一个许可的线程。如果第一个线程在等待一个许可时发生阻塞,而第二个线程  前来索要一个许可的时候刚好有一个许可被释放出来,那么它就可能会在第一个线程之前获得许可。 如果你想要强制公平,Semaphore 类有一个具有一个布尔类型的参数的构造子,通过这个参数以告知   Semaphore 是否要强制公平。强制公平会影响到并发性能,所以除非你确实需要它否则不要启用它。

      以下是如何在公平模式创建一个 Semaphore 的示例:

      Semaphore semaphore = new Semaphore(1, true); 

    4.执行器服务 ExecutorService
    java.util.concurrent.ExecutorService 接口表示一个异步执行机制,使我们能够在后台执行任务。因此一个 ExecutorService 很类似于一个线程池。实际上,
    存在于 java.util.concurrent 包里的 ExecutorService 实现就是一个线程池实现。

      以下是一个简单的 ExecutorService 例子:

    1 ExecutorService executorService = Executors.newFixedThreadPool(10);  
    2 
    3 executorService.execute(new Runnable() {  
    4     public void run() {  
    5         System.out.println("Asynchronous task");  
    6     }  
    7 });  
    8 
    9 executorService.shutdown();  

      首先使用 newFixedThreadPool() 工厂方法创建一个 ExecutorService。这里创建了一个十个线程执行任务的线程池。
      然后,将一个 Runnable 接口的匿名实现类传递给 execute() 方法。这将导致 ExecutorService 中的某个线程执行该 Runnable。

      *通过submit(Runnable)方法来运行任务与execute类似,submit(Runnable) 方法也要求一个 Runnable 实现类,但它返回一个 Future 对象。这个 Future 对象可以用来检查 Runnable 是否已经执行完毕。

    5.ScheduledExecutorService

      java.util.concurrent.ScheduledExecutorService 是一个 ExecutorService, 它能够将任务延后执行,或者间隔固定时间多次执行。 任务由一个工作者线程异步执行,而不是由提交任务给       ScheduledExecutorService 的那个线程执行。

     1 ScheduledExecutorService scheduledExecutorService =  
     2         Executors.newScheduledThreadPool(5);  
     3 
     4 ScheduledFuture scheduledFuture =  
     5     scheduledExecutorService.schedule(new Callable() {  
     6         public Object call() throws Exception {  
     7             System.out.println("Executed!");  
     8             return "Called!";  
     9         }  
    10     },  
    11     5,  
    12     TimeUnit.SECONDS); 

    首先一个内置 5 个线程的 ScheduledExecutorService 被创建。之后一个 Callable 接口的匿名类示例被创建然后传递给 schedule() 方法。后边的俩参数定义了 Callable 将在 5 秒钟之后被执行。*正如 ExecutorService,在你使用结束之后你需要把 ScheduledExecutorService 关闭掉。否则他将导致 JVM 继续运行,即使所有其他线程已经全被关闭。你可以使用从 ExecutorService 接口继承来的 shutdown() 或 shutdownNow() 方法将 ScheduledExecutorService 关闭。参见 ExecutorService 关闭部分以获取更多信息。

    6.读写锁 ReadWriteLock

    java.util.concurrent.locks.ReadWriteLock 读写锁是一种先进的线程锁机制。它能够允许多个线程在同一时间对某特定资源进行读取,但同一时间内只能有一个线程对其进行写入。

    读写锁的理念在于多个线程能够对一个共享资源进行读取,而不会导致并发问题。并发问题的发生场景在于对一个共享资源的读和写操作的同时进行,或者多个写操作并发进行。

    本节只讨论 Java 内置 ReadWriteLock。如果你想了解 ReadWriteLock 背后的实现原理,请参考我的《Java 并发指南》主题中的《读写锁》小节。

    ReadWriteLock 锁规则

    一个线程在对受保护资源在读或者写之前对 ReadWriteLock 锁定的规则如下:
    读锁:如果没有任何写操作线程锁定 ReadWriteLock,并且没有任何写操作线程要求一个写锁(但还没有获得该锁)。因此,可以有多个读操作线程对该锁进行锁定。

    写锁:如果没有任何读操作或者写操作。因此,在写操作的时候,只能有一个线程对该锁进行锁定。

    ReadWriteLock 实现

    ReadWriteLock 是个接口,如果你想用它的话就得去使用它的实现类之一。java.util.concurrent.locks 包提供了 ReadWriteLock 接口的以下实现类:ReentrantReadWriteLock

    ReadWriteLock 代码示例

    以下是 ReadWriteLock 的创建以及如何使用它进行读、写锁定的简单示例代码:

     1 ReadWriteLock readWriteLock = new ReentrantReadWriteLock();  
     2 
     3 readWriteLock.readLock().lock();  
     4 
     5 // multiple readers can enter this section  
     6 // if not locked for writing, and not writers waiting  
     7 // to lock for writing.  
     8 
     9 readWriteLock.readLock().unlock();  
    10 
    11 readWriteLock.writeLock().lock();  
    12 
    13 // only one writer can enter this section,  
    14 // and only if no threads are currently reading.  
    15 
    16 readWriteLock.writeLock().unlock();
  • 相关阅读:
    【随机过程】马尔可夫链(2)
    【机器学习】机器学习中的各种相似性、距离度量
    【机器学习】机器学习中的各种相似性、距离度量
    嵌入式开发之8127---DM8127如何利用EDMA搬移数据
    嵌入式开发之8127---核心板原理图
    8148和8127中的ezsdk和dvrsdk
    dm385和8127的区别
    Appro DM8127 IPNC 挂载NFS遇到的问题及解决
    嵌入式开发之cmos---前端采集aptina cmos
    阶段1 语言基础+高级_1-3-Java语言高级_09-基础加强_第2节 反射_11_反射_案例
  • 原文地址:https://www.cnblogs.com/singular/p/10418203.html
Copyright © 2020-2023  润新知