读《Java并发编程的艺术》学习笔记(八)
第8章 Java中的并发工具类
在JDK的并发包里提供了几个非常有用的工具类。CountDownLatch、CyclicBarrier和Semaphore工具类提供了一种并发流程控制的手段,Exchanger工具类提供了在线程间交换数据的一种手段。
8.1 等待多线程完成的CountDownLatch
CountDownLatch允许一个或多个线程等待其他线程完成操作。
在JDK1.5之前,我们要达到一个或多个线程等待其他线程完成操作,需要使用thread.join()方法,不停检查等待的线程是否存活。而CountDownLatch的出现给我们提供了一种功能更强大、更优雅的方法。
CountDwonLatch的构造方法结构一个int类型的参数作为计数器的值,如果需要等待N个线程完成工作,那就传入N。
调用countDown()方法,计数器值会减1,当计数器值为0时,会唤醒被await阻塞的线程。CountDownLatch同样提供超时时间的await(long time,TimeUnit unit)。如果到了指定的时间,计数器仍然不为0,则同样会唤醒线程。
【备注】:CountDownLatch不能重新初始化或修改其内部计数器的值。
8.2 同步屏障CyclicBarrier
CyclicBarrer的作用是让一组线程达到一个屏障(同步点)时被阻塞,直到所有的线程到达此屏障时,才会唤醒被屏障阻塞的所有线程。
CyclicBarrier默认构造方法CyclicBarrier(int parties),需要传入屏障需要拦截的线程数量。每个线程通过调用await方法告诉CyclicBarrier已经到达屏障,随后被阻塞,直到所有线程到达屏障或线程被中断才被唤醒。
CyclicBarrier还提供一个更高级的构造函数CyclicBarrier(int parites,Runnable barrierAction),用于在所有线程到达屏障并被唤醒时,优先执行barrierAction。
CyclicBarrier和CounDownLatch的区别
- CountDownLatch的计数器只能使用一次,而CyclicBarrier计数器可以使用reset()方法重置。
- CyclicBarrier还提供获取阻塞线程数量及检测阻塞线程是否被中断等CountDownLatch没有的方法。
【备注】: CountDownLatch的getCount()方法返回还有多少需要调用countDown方法去tryReleaseShared使计数器归0的线程数量。CyclicBarrier的getParties()方法同样返回需要到达屏障的线程数量。
8.3 控制并发线程数的Semaphore
Semaphore(信号量)是用来控制同时访问特定资源的线程数量,它通过协调各个线程,以保证合理的使用公共资源。
Semaphore(2)表示允许2个线程获取许可证,也就是最大并发数为2。通过调用acquire()方法获取许可证,使用完毕之后调用release()方法归还许可证。
除此之外,Semaphore还提供一些其他方法:
- intavailablePermits():返回此信号量中当前可用的许可证数。
- intgetQueueLength():返回正在等待获取许可证的线程数。
- booleanhasQueuedThreads():是否有线程正在等待获取许可证。
- void reducePermits(int reduction):减少reduction个许可证,是个protected方法。
- Collection getQueuedThreads():返回所有等待获取许可证的线程集合,是个protected方法。
8.4 线程间交换数据的Exchanger
Exchanger(交换者)是一个用于线程协作的工具类。用于进行线程间的数据交换。Exchanger提供一个同步点,在这个同步点,两个线程可以交换彼此的数据。线程通过调用Exchanger的exchange()方法来通知Exchanger已经到达同步点,并被阻塞直到另外一个线程也调用exchange()方法到达同步点时,两个线程才可以交换数据。