同步器有哪些?
类 | 它能做什么 | 说明 |
---|---|---|
CyclicBarrier | 允许线程集等待直至其中预定数目的线程到达一个公共障栅,然后可以选择执行一个处理障栅的动作 | 当大量的线程需要在它们的结果可用之前完成时 |
Phaser | 类似与循环障栅,不过有一个可变的计数 | JAVA SE7引入 |
CountDownLatch | 允许线程集等待知道计数器减为0 | 当一个或多个线程需要等待直到指定数目的事件发生 |
Exchanger | 允许两个线程在要交换的对象准备好时交换对象 | 当两个线程工作在同一数据结果的两个实例上的适合,一个向实例添加数据而另一个从实例清除数据 |
Semaphore | 允许线程集等待直到被允许继续运行为止 | 限制访问资源的线程总数。 |
SynchronousQueue | 允许一个线程把对象交给另一个线程 | 在没有显式同步的情况下,当两个线程准备好将一个对象从一个线程传递到另一个时 |
信号量
为了通过信号量,线程通过调用acquire请求许可。其实没有实际的许可对象,信号量仅维护一个计数。许可的数目是固定的,由此限制了通过的线程数量。其他线程可以通过调用release释放许可。
倒计时门栓
一个CountDownLatch让一个线程集等待直到计数变为0。倒计时门栓是一次性的,一旦计数为0,就不能用了。
障栅
CyclicBarrier实现了一个集结点(rendezvous)成为障栅(barrier),当一个线程完成了它那部分任务后,我们让它运行到barrier,一旦所有线程都到达了这个barrier,barrier就撤销了。
CyclicBarrier barrier = new CyclicBarrier(nthreads);
public void run() {
doWork();
barrier.await();
}
因为是循环的,所以是可以在所有等待线程被释放后被重用的。
Phaser
与CyclicBarrier类似,但更灵活,可以改变不同阶段中参与线程的个数。
交换器Exchanger
可以交换两个线程的数据,相当于共享。典型情况是,一个线程向缓冲区填入数据,另一个线程消耗这些数据。当它们都完成后,相互交换缓冲区。
同步队列
当一个线程调用SynchronousQueue的put方法时,它会阻塞直到另一个线程调用take方法为止,反之亦然。虽然它实现了BlockingQueue接口,但概念上讲,它并不是一个队列,因为它并没有包含任何元素,它的size总是为0。