参考书籍:《Java并发编程实战》
闭锁
一种同步工具类,可以延迟线程的进度直到其达到终止状态。
作用:相当于一扇门,在闭锁达到结束状态之前,折扇门一直关闭,并且没有任何线程通过,当达到结束状态时,这扇门才会打开,并允许所有的线程通过。当闭锁达到结束状态后,将不会再改变状态,因此这扇门会永远保持打开状态。
使用场景
- 确保某个计算在其需要的所有资源都被初始化之后才能继续执行。
- 确保某个服务在其依赖的所有其他服务都启动之后才能启动。(每个服务都有一个相关的二元闭锁)
- 等待直到某个操作的所有参与者(如游戏玩家)都就绪再执行。(当所有玩家准备就绪时,闭锁将到达结束状态)
Java中闭锁的实现:CountDownLatch
示例:
import java.util.concurrent.CountDownLatch;
/**
* Created by zfr on 2018/08/30.
*/
public class TestHarness {
public static void main(String args[]){
TestHarness test = new TestHarness();
long res = test.timeTasks(3, new Runnable() {
@Override
public void run() {
System.out.println(Thread.currentThread().getName()+"say hi!");
}
});
System.out.println(res);
}
/**
* * 创建一定的线程,利用他们并发地执行指定任务
* 每个工作线程首先要做的事就是在启动门上等待,从而确保所有线程都就绪后才开始执行
* 而每个线程要做的最后一件事就是调用结束门的countDown方法减1,使得主线程高效地等待直到所有工作线程都执行完
* 因此可以统计所消耗的时间
* @date 2018/08/30
* * @Param: nThreads 线程数
* * @Param: task 要执行的任务
**/
public long timeTasks(int nThreads,final Runnable task){
//CountDownLatch是一种灵活的闭锁实现
final CountDownLatch startGate = new CountDownLatch(1);//起始门
final CountDownLatch endGate = new CountDownLatch(nThreads);//结束门
for(int i = 0 ;i < nThreads; i++){
Thread t = new Thread(){
@Override
public void run() {
try{
startGate.await();//await()等待计数器到达0,表示所有等待的事件都已经发生
try{
task.run();
}finally {
endGate.countDown();//countDown()递减计数器
}
}catch (InterruptedException ignored){
}
}
};
t.start();
}
long start = System.nanoTime();//系统计时器的当前值,以毫微秒为单位。
startGate.countDown();
try{
endGate.await();
}catch (InterruptedException ignored){
}
long end = System.nanoTime();
return end - start ;
}
}