问题背景:
问题一:
java多线程,A、B、C、D统计4个盘大小,统计完后第5个人汇总。
问题二:
比如一个团队赛跑游戏,最后要计算团队赛跑的成绩,主线程计算最后成绩,要等到所有团队成员跑完,方可计算总成绩。
java.util.concurrent.CountDownLatch
你可以向 CountDownLatch 对象设置一个初始计数值,任何在这个对象上调用 await() 的方法都将阻塞,直到这个计数值为0。其他任务在结束其工作时,可以在该对象上调用 countDown() 来减小这个数值,这个方法不会阻塞线程。 CountDownLatch 被设计为只触发一次,计数值不能被重置。如果你需要能够重置计数值的版本,则可以使用 CyclicBarrier .
CountDownLatch 的典型用法时将一个程序分成n个互相独立的可解决任务,并创建值为n的CountDownLatch。每当任务完成时,都会在这个锁存储器上调用countDown()方法。等待问题被解决的任务在这个锁存储器上调用await()。将它们自己拦住,直到存储器计数结束。
示例1:通用代码示例
import java.util.concurrent.CountDownLatch;
/**
* 比如一个团队赛跑游戏,最后要计算团队赛跑的成绩,主线程计算最后成绩,要等到所有
* 团队成员跑完,方可计算总成绩。
*
* 题目2:统计4个盘子的大小,统计完后交给第五个人汇总
*/
public class CountDownLatchTest {
public static void main(String[] args) throws InterruptedException {
CountDownLatch startSignal = new CountDownLatch(1);
CountDownLatch doneSignal = new CountDownLatch(4);
//四个人赛跑,这4个可以写一个for循环
new Thread(new Worker(startSignal, doneSignal)).start();
new Thread(new Worker(startSignal, doneSignal)).start();
new Thread(new Worker(startSignal, doneSignal)).start();
new Thread(new Worker(startSignal, doneSignal)).start();
System.out.println("这里放计数前自己的代码...");//由于startSignal是1,上边的4个线程还不能执行
startSignal.countDown(); // startSignal=0,线程可以开始执行了
//doSomethingElse();
System.out.println("计数后的代码...这是主线程...和上边4个线程混在一起的...");
doneSignal.await(); // 判断上边4个是否执行完了,如果是,则允许下边的代码执行
//开始执行另外一个任务
System.out.println("开始执行其他任务...");
}
}
class Worker implements Runnable {
private final CountDownLatch startSignal;
private final CountDownLatch doneSignal;
Worker(CountDownLatch startSignal, CountDownLatch doneSignal) {
this.startSignal = startSignal;
this.doneSignal = doneSignal;
}
@Override
public void run() {
try {
startSignal.await(); //startSignal的计数到0了吗?到0了,才能执行
doWork();
doneSignal.countDown();
} catch (InterruptedException ex) {
}
}
void doWork() {
System.out.println("正在统计中...");
}
}
//结果
这里放计数前自己的代码...
计数后的代码...这是主线程...和上边4个线程混在一起的...
正在统计中...
正在统计中...
正在统计中...
正在统计中...
开始执行其他任务...