JUC并发工具包中提供了CountDownLatch, CyclicBarier, Semaphore作为并发流程控制的手段。
CountDownLatch
CountDownLatch允许一个或多个线程等待其他线程完成操作。
在CountDownLatch之前,通常使用join()方法实现等待其他线程的操作。
t1.join();
t1.join()中实现等待的逻辑为
while (isAlive()) {
wait(0);
}
如果t1线程存活,则调用当前线程的wait()方法陷入无限期等待,当前线程进入t1线程对象对应的Monitor的wait队列,当t1线程结束时,会由虚拟机调用t1.notifyAll()唤醒所有等待t1线程对象的线程。
CountDownLatch提供了比join()方法更强大的功能。
CountDownLatch的构造函数接收一个int类型的参数作为计数器,如果你想等待N个点完 成,这里就传入N。 当我们调用CountDownLatch的countDown方法时,N就会减1,CountDownLatch的await方法 会阻塞当前线程,直到N变成零。由于countDown方法可以用在任何地方,所以这里说的N个 点,可以是N个线程,也可以是1个线程里的N个执行步骤。用在多个线程时,只需要把这个 CountDownLatch的引用传递到线程里即可。
CountDownLatch内部也是由一个继承了AQS的Sync类实现。
同步屏障CyclicBarrier
CyclicBarrier的字面意思是可循环使用(Cyclic)的屏障(Barrier)。它要做的事情是,让一组线程到达一个屏障(也可以叫同步点)时被阻塞,直到最后一个线程到达屏障时,屏障才会 开门,所有被屏障拦截的线程才会继续运行。
CyclicBarrier和CountDownLatch的区别
CountDownLatch的计数器只能使用一次,而CyclicBarrier的计数器可以使用reset()方法重 置。所以CyclicBarrier能处理更为复杂的业务场景。例如,如果计算发生错误,可以重置计数 器,并让线程重新执行一次。
控制并发线程数的Semaphore
Semaphore(信号量)是用来控制同时访问特定资源的线程数量,它通过协调各个线程,以 保证合理的使用公共资源。
Semaphore的用法也很简单,首先线程使用 Semaphore的acquire()方法获取一个许可证,使用完之后调用release()方法归还许可证。还可以 用tryAcquire()方法尝试获取许可证。
Semaphore实际上把信号量赋值给了内部AQS的state字段。
调用acquire实际上调用了AQS的acquireSharedInterruptibly方法,内部再调用了由Sync实现的nonfairTryAcqureShared。acquire则 CAS设置state -= 1。