CountDownLatch可用于一个线程等待另外一些线程做了一些事后再做自己的事。做事的线程做完事后报一下数:将一个初数值减1,等这个数值变成0时,等待的线程就可以做自己的事。
用join()也能完成相同的目标。但join()意味着必须等待做事线程终止自己才能动手,CountDownLatch没有这个限制,做事线程再报完数后还可以继续做自己的事。
package player.kent.chen.learn.countdownlatch; import java.util.concurrent.CountDownLatch; public class HelloLatch { private static class Begger implements Runnable { private CountDownLatch latch; public Begger(CountDownLatch latch) { super(); this.latch = latch; } public void run() { try { System.out.println("我是乞丐,要钱吃饭"); latch.await(); //等待别人报数完毕 System.out.println("我是乞丐,钱要够了,现在去买吃的"); } catch (InterruptedException e) { Thread.currentThread().interrupt(); } } } private static final class Walker implements Runnable { private CountDownLatch latch; public Walker(CountDownLatch latch) { this.latch = latch; } public void run() { takeTime(3000l); System.out.println("我是行人" + Thread.currentThread().getName() + " 我走到乞丐跟前花了3秒钟,然后给了乞丐一块钱"); latch.countDown(); //给完钱后,报数 takeTime(10000l); //报完数后,继续做自己的事,线程仍然活着 System.out.println("我是行人" + Thread.currentThread().getName() + " 给完钱后,我在无边的人海中继续前行直到永远。。。"); takeTime(Long.MAX_VALUE); } private void takeTime(long time) { try { Thread.sleep(time); } catch (InterruptedException e) { } } } public static void main(String[] args) throws InterruptedException { int count = 3; CountDownLatch latch = new CountDownLatch(count); new Thread(new Begger(latch)).start(); Thread.sleep(3000); Thread[] threads = new Thread[count]; for (int i = 0; i < threads.length; i++) { threads[i] = new Thread(new Walker(latch)); threads[i].setName("walker" + i); } for (Thread thread : threads) { thread.start(); System.out.println(thread.getName() + " 已经动身了 "); Thread.sleep(1000l); //动身时间间隔一秒 } } }
执行结果:
我是乞丐,要钱吃饭
walker0 已经动身了
walker1 已经动身了
walker2 已经动身了
我是行人walker0 我走到乞丐跟前花了3秒钟,然后给了乞丐一块钱
我是行人walker1 我走到乞丐跟前花了3秒钟,然后给了乞丐一块钱
我是行人walker2 我走到乞丐跟前花了3秒钟,然后给了乞丐一块钱
我是乞丐,钱要够了,现在去买吃的
我是行人walker0 给完钱后,我在无边的人海中继续前行直到永远。。。
我是行人walker1 给完钱后,我在无边的人海中继续前行直到永远。。。
我是行人walker2 给完钱后,我在无边的人海中继续前行直到永远。。。
同时各行人线程仍处于alive状态。