本文总结自《Java并发编程的艺术》
等待多线程完成的CountDownLatch
- CountDownLatch允许一个或多个线程等待其他线程完成操作。CountDownLatch的构造函数接收一个int类型的参数作为计数器,如果你想等待N个线程完成任务,这里就传入N。当我们调用CountDownLatch的countDown方法时,N就会减1。可以使用CountDownLatch的await()方法(也可以使用另一个带指定时间的await(long time, TimeUnit unit)方法)阻塞当前线程,直到N变为0。如果想在多线程情况下使用,只需要把这个CountDownLatch的引用传递到线程里即可。
5.8.2 同步屏障CyclicBarrier
- 字面意思为可循环使用的屏障。它主要做的事情是让一组线程到达一个屏障时被阻塞,直到最后一个线程到达屏障时,屏障才会开门,所有被拦截的线程才会运行。CyclicBarrier默认的构造方法是CyclicBarrier(int parties):其参数表示屏障拦截的线程数量,每个线程可以通过CyclicBarrier的引用调用await方法告诉CyclicBarrier我已到达屏障,然后当前线程被阻塞。CyclicBarrier还提供了一个更高级的构造函数CyclicBarrier(int parties, Runnable barrierAction):用于在所有线程到达屏障时,优先执行barrierAction。
- CountDownLatch的计数器只能使用一次,而CyclicBarrier的计数器可以通过reset()方法重置。CyclicBarrier还可以通过getNumberWaiting方法获取阻塞的线程数量。通过isBroken方法来了解阻塞的线程是否被中断。
- CyclicBarrier的计数器如果已经到达线程数,那么他会自动归零。
5.8.3 控制并发线程数的Semaphore
- Semaphore是用来控制同时访问特定资源的线程数量。Semaphore的构造方法接受一个整形的数字表示可用的许可证数量(只有拿到许可证的线程才可以执行,否则会被阻塞),还可以接受一个boolean变量用来表示等待队列中的线程竞争锁是否公平,默认为非公平,可以让该参数为true来创建一个公平的Semaphore。线程使用Semaphore的acquire()方法获取一个许可证,使用完之后调用release()方法归还。也可以通过tryAcquire()尝试获取许可证。
5.8.4 线程间交换数据的Exchanger
- Exchanger用于进行线程间的数据交换。它提供一个同步点,在这个同步点,两个线程可以交换彼此的数据。这两个线程通过exchange(Elemeng E)方法交换数据。如果一个线程先执行exchange(Elemeng E)方法,他会一直等待第二个线程也执行exchange(Elemeng E)方法。为了避免一直等待,可以使用exchange(V x, long timeout, TimeUnit unit)设置最大等待时长。