java 倒计时门栓 是指Java的CountDownLatch类;它是Java用于并发编程的辅助类中的其中一个。它的主要功能正如其名称所示:以倒计时为门栓标准。指定线程只有计数为0时,系统才会放开权限让该线程开始执行。CountDownLatch类常用于指定某个工作线程只有等待其他准备线程都准备完(count计数也就变为0)才能开始执行具体的工作任务
public class Test{
public static void main(String[] arg){
//定义一个大小为3的 倒计时门栓 用于确认多个线程已经执行完毕
//即 countDownLatch.await()之后的代码必须等待countDownLatch.countDown()调用知道countDownLatch大小减少到0
CountDownLatch countDownLatch = new CountDownLatch(3);
AtomicInteger num = new AtomicInteger();
ThreadPoolExecutor pool = new ThreadPoolExecutor(
3,
3,
1000,
TimeUnit.SECONDS,
new LinkedBlockingDeque<>(10),new ThreadFactory() {//线程工厂
@Override
public Thread newThread(Runnable r) {
Thread thread = new Thread(Thread.currentThread().getThreadGroup(), r, "test-thread-"+num.getAndIncrement());
thread.setUncaughtExceptionHandler(new UncaughtExceptionHandler() {
@Override
public void uncaughtException(Thread t, Throwable e) {
System.out.println(t.getName()+"发生了异常:"+e.getMessage());
}
});
return thread;
}
},new RejectedExecutionHandler(){//拒绝策略
@Override
public void rejectedExecution(Runnable r, ThreadPoolExecutor executor) {
throw new RuntimeException("任务呗拒绝,请调整阻塞队列大小");
}
});
//模拟一个场景:王老师想要统计小张、小王、小李三位同学的数学期末考试得分,并计算总分
//但是这三位同学都忘记了自己的得分,但是可以回家去看看试卷。
//小张回家后三秒钟,老师知道了小张得到了 98分
Future<Integer> xiaozhang = pool.submit(()->{
Thread.sleep(3000);
countDownLatch.countDown();
return 93;
});
//小王回家后一秒钟,老师知道了小张得到了 98分
Future<Integer> xiaowang = pool.submit(()->{
Thread.sleep(1000);
countDownLatch.countDown();
return 98;
});
//小李回家后五秒钟,老师知道了小张得到了 98分
Future<Integer> xiaoli = pool.submit(()->{
Thread.sleep(5000);
countDownLatch.countDown();
return 94;
});
Runnable laoshi = ()-> {
try {
//老师等待三位同学都返回自己的得分后才能继续运行
countDownLatch.await();
int total = xiaoli.get()+xiaowang.get()+xiaozhang.get();
System.out.println(total);
Thread.sleep(3000);
} catch (InterruptedException | ExecutionException e) {
e.printStackTrace();
}
};
new Thread(laoshi,"test-thread-teacher").start();//老师统计得分
if(Thread.activeCount()>1){
Thread.yield();
}
pool.shutdown();
}
}
注意:CountDownLatch内部通过共享锁实现。在创建CountDownLatch实例时,需要传递一个int型的参数:count,该参数为计数器的初始值,也可以理解为该共享锁可以获取的总次数。当某个线程调用await()方法,程序首先判断count的值是否为0,如果不会0的话则会一直等待直到为0为止。当其他线程调用countDown()方法时,则执行释放共享锁状态,使count值 - 1。当在创建CountDownLatch时初始化的count参数,必须要有count线程调用countDown方法才会使计数器count等于0,锁才会释放,前面等待的线程才会继续运行。注意CountDownLatch不能回滚重置