JDK-CountDownLatch-实例、源码和模拟实现
根据CountDownLatch的document,就是说CountDownLatch作为一个同步的助手,可以阻塞一个线程,等待另一个线程结束了再执行。所以CountDownLatch的作用在于:通过阻塞来协调线程间的执行顺序。
CountDownLatch最重要的方法为await()和countDown()。首先,初始化指定一个count,每次countDown()都会count--,而await()就是阻塞调用它的方法,直到count==0。
所以可以把CountDownLatch看成同步的计数器,什么时候倒数到0就执行,否则阻塞。
Demo
我们首先做一个CountDownLatch的demo,看看它是怎么一个阻塞。
count初始化为2,所以count.await()会阻塞主线程,直到两个processor都countDown(),即count==0的时候才会执行,打印出"Processors has been done."
[java]
public class CountDownLatchTest {
public static void main(String[] args) throws InterruptedException {
CountDownLatch count = new CountDownLatch(2);
ExecutorService exc = Executors.newSingleThreadExecutor();
System.out.println("Before submit the processor.");
exc.submit(new CountProcessor(count, "P1"));
exc.submit(new CountProcessor(count, "P2"));
System.out.println("Has submited the processor.");
count.await();
System.out.println("Processors has been done.");
exc.shutdown();
}
}
class CountProcessor extends Thread {
private CountDownLatch count;
private String name;
public CountProcessor(CountDownLatch count, String name) {
this.count = count;
this.name = name;
}
@Override
public void run() {
try {
Thread.currentThread().sleep(1000);
System.out.println(this.name + " has been done.");
count.countDown();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
修改一下上面的程序,我们可以模拟一个百米赛跑的现场:
首先运动员进场:前期数据准备和线程池的初始化。
准备工作完成后统一起跑:传入的begin.await()一直阻塞着Runner.run(),在前期准备完成后,begin.countDown()后begin.count==0,阻塞结束,Runner起跑。
比赛一直进行,直到所有选手冲过终点:end.await()会阻塞主线程,所以最后的那条print语句不会提前打印,而是等待Runner.run()结束执行end.countDown(),减少3次直到end.count==0才接触阻塞,宣布比赛结束。
这就是CountDownLatch的经典场景,统一开始,统一结束。
[java]
public class CountDownLatchTest {
public static void main(String[] args) throws InterruptedException {
CountDownLatch begin = new CountDownLatch(1);
CountDownLatch end = new CountDownLatch(3);
ExecutorService exc = Executors.newCachedThreadPool();
System.out.println("Runners are comming.");
exc.submit(new CountProcessor(begin, end, "Runner_1", 1000));
exc.submit(new CountProcessor(begin, end, "Runner_2", 2000));
exc.submit(new CountProcessor(begin, end, "Runner_3", 3000));
System.out.println("Ready.");
Thread.currentThread().sleep(1000);
System.out.println("Go.");
begin.countDown();
end.await();
System.out.println("All runners Finish the match.");
exc.shutdown();
}
}
class CountProcessor extends Thread {
private CountDownLatch beginCount;
private CountDownLatch endCount;
private String name;
private int runningTime;
public CountProcessor(CountDownLatch beginCount, CountDownLatch endCount, String name, int runningTime) {
this.beginCount = beginCount;
this.endCount = endCount;
this.name = name;
this.runningTime = runningTime;
}
@Override
public void run() {
try {
this.beginCount.await();
System.out.println(this.name + " start.");
Thread.currentThread().sleep(this.runningTime);
System.out.println(this.name + " breast the tape.");
this.endCount.countDown();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
Source Code
我们来看JDK中CountDownLatch是怎么定义的,以及其中的主要方法。
[java]
public class CountDownLatch {
public CountDownLatch(int count) {
if (count < 0) throw new IllegalArgumentException("count < 0");
this.sync = new Sync(count);
}
public void await() throws InterruptedException {
sync.acquireSharedInterruptibly(1);
}
public void countDown() {
sync.releaseShared(1);
}
public long getCount() {
return sync.getCount();
}
}
&n
补充:软件开发 , Java ,
- 更多JAVA疑问解答:
- java怎么在线读取ftp服务器上的文件内容
- 关于程序员的职业规划
- HTML和JSP矛盾吗?
- java小程序如何打包?
- java怎么split路径文件名?
- 关于Hibernate实体自身多对一的抓取问题
- 关于apache2+tomcat群集出现的问题
- SSH 导入导出excel 谁有这块的资料吗?
- springmvc 加载一个jsp页面执行多个方法 报404
- 关于用jquery 导入 excel
- java对时间进行循环放到List中
- 一个图片的输入输出程序,第一次调用某方法会中断,第二次调用则正常
- 请上过传智播客的人说一下传智播客怎么样呀!是不是像它说的那样好呀!
- spring的schema怎么配置
- 【菜鸟求助】SSH中怎么从JSP页面往后台传值呢