常用并发类

CountDownLatch(闭锁)

CountDownLatch可以用来实现一个(或者多个)线程等待其他线程完成一组特定的操作之后才继续运行。CountDownLatch. await()用于线程暂停,CountDownLatch. countDown()用于计数器减少,当减为0时暂停的线程继续; 一个CountDownLatch实例只能够实现一次等待和唤醒。
latch = new CountDownLatch( 3);
latch. await();
latch. countDown();此方法需要放在finally中
CountDownLatch. await( long, TimeUnit) 允许指定一个超时时间,在该 时间内如果相应CountDownLatch实例的 计数器值仍然未达到0,那么所有执行该实例的await方法的线程都会被唤醒。该方法 的返回值可用于区分其返回是否是由于等待超时。

CyclicBarrier(栅栏)

线程相互等待到某一地点同时继续运行。使用CyclicBarrier实现等待的线程被称为参与方,参与方只需要执行 CyclicBarrier.await()就可以实现等待。除最后一个线程外的任何参与方执行CyclicBarrier.await()都会导致该线程被 暂停( 线程生命周期状态变为WAITING)。最后一个线程执行CyclicBarrier. await() 会使得使用相应CyclicBarrier 实例的其他所有参与方被唤醒,而最后一个线程自身并不会被暂停。
CyclicBarrier实例是可重复使用的:所有参与方被唤醒的时候,任何线程再次执行CyclicBarrier. await()又会被暂停,直到这些线程中的最后一个线程执行了CyclicBarrier.await()。
startBarrier = new CyclicBarrier( N);
startBarrier. await();
一般用于循环使用的高并发场景

阻塞队列(BlockingQueue)

BlockingQueue的常用实现类包括ArrayBlockingQueue、LinkedBlockingQueue和SynchronousQueue等。
阻塞队列按照其存储空间的容量是否受限制来划分,可分为有界队列(Bounded Queue)和无界队列( Unbounded Queue)。有界队列的存储容量限制是由应用程序指定的,无界队列的最大存储容量为 Integer. MAX_ VALUE( 2^31-1)个元素。
使用有界队列作为传输通道的另外一个好处是可以造成"反压"的效果,当然,这里的代价是可能增加的上下文切换。
ArrayBlockingQueue只能实现有界队列,内部使用一个数组作为其存储空间,put操作、take操作本身并不会增加垃圾回收的负担。缺点是其内部在实现put、take操作的时候使用的是同一个锁(显式锁),从而可能导致锁的高争用, 进而导致较多的上下文切换。
LinkedBlockingQueue既能实现无界队列,也能实现有界队列。LinkedBlockingQueue 的优点是其内部在实现 put、 take 操作的时候分别使用了两个显式锁( putLock 和 takeLock),这降低了锁争用的可能性。LinkedBlockingQueue 的内部存储空间是一个链表,put 操作、take操作都会导致链表节点的动态创建和移除,因此LinkedBlockingQueue 的缺点是它可能增加垃圾回收的负担。 另外, 由于 LinkedBlockingQueue 的 put、take操作使用的是两个锁,因此LinkedBlockingQueue维护其队列的当前长度( size) 时无法使用一个普通的int型变量而是使用了一个原子变量( AtomicInteger)。这个原子变量可能会被生产者线程和消费者线程争用, 因此它可能导致额外的开销。
SynchronousQueue 可以被看作一种特殊的有界队列。 SynchronousQueue 内部并不维护用于存储队列元素的存储空间。生产者和消费者交替阻塞。
占用队列的线程可以对队列进行put或者take操作,那么对队列( 作为一种资源)的调度就是决定哪个线程可以进行 put或者take操作的过程。 ArrayBlockingQueue 和 SynchronousQueue 都既支持非公平调度也支持公平调度, 而 LinkedBlockingQueue 仅支持非公平调度。
LinkedBlockingQueue 适合在生产者线程和消费者线程之间的并发程度比较大的情况下使用。 ArrayBlockingQueue 适合在生产者线程和消费者线程之间的并发程度较低的情况下使用。
SynchronousQueue 适合在消费者处理能力与生产者处理能力相差不大的情况下使用。

Semophore(信号量)

为了实现限流,利用Semaphore在获取资源前先申请相应的配额,并在资源访问结束后返还相应的配额。Semaphore.acquire()/release()分别用于申请配额和返还配额。Semaphore. acquire() 在成功获得一个配额后会立即返回。如果当前的可用配额不足,那么Semaphore. acquire() 会使其执行线程暂停。 Semaphore内部会维护一个等待队列用于存储这些被暂停的线程。 Semaphore. acquire() 在其返回之前总是会将当前的可用配额减少1。 Semaphore. release() 会使当前可用配额增加1, 并唤醒相应Semaphore 实例的等待队列中的一个任意等待线程。
Semaphore. acquire() 和 Semaphore. release() 总是配对使用的,这点需要由应用代码自身来保证。
Semaphore. release() 调用总是应该放在一个finally块中,以避免虚拟资源访问出现异常的情况下当前线程所获得的配额无法返还。
默认情况下,Semaphore采用的是非公平性调度策略。

Exchanger(交换器)

功能类似于SynchronousQueue

原文地址:https://www.cnblogs.com/lllliuxiaoxia/p/15769388.html