java线程中锁存器CountDownLatch的使用

CountDownLatch类是一个同步计数器,构造时传入int参数,该参数就是计数器的初始值,每调用一次countDown()方法,计数器减1,计数器大于0 时,await()方法会阻塞程序继续执行。CountDownLatch可以看作是一个倒计数的锁存器,当计数减至0时触发特定的事件。利用这种特性,可以让主线程等待子线程的结束。下面以一个模拟运动员比赛的例子加以说明。

CountDownLatch的一个非常典型的应用场景是:有一个任务想要往下执行,但必须要等到其他的任务执行完毕后才可以继续往下执行。假如我们这个想要继续往下执行的任务调用一个CountDownLatch对象的await()方法,其他的任务执行完自己的任务后调用同一个CountDownLatch对象上的countDown()方法,这个调用await()方法的任务将一直阻塞等待,直到这个CountDownLatch对象的计数值减到0为止。

1importjava.util.concurrent.CountDownLatch;2importjava.util.concurrent.Executor;3importjava.util.concurrent.ExecutorService;4importjava.util.concurrent.Executors;56publicclassCountDownLatchDemo {7privatestaticfinalintPLAYER_AMOUNT=5;8publicCountDownLatchDemo() {9//TODO Auto-generated constructor stub10}11/**12*@paramargs13*/14publicstaticvoidmain(String[] args) {15//TODO Auto-generated method stub16//对于每位运动员,CountDownLatch减1后即结束比赛17CountDownLatch begin=newCountDownLatch(1);18//对于整个比赛,所有运动员结束后才算结束19CountDownLatch end=newCountDownLatch(PLAYER_AMOUNT);20Player[] plays=newPlayer[PLAYER_AMOUNT];2122for(inti=0;i<PLAYER_AMOUNT;i++)23plays[i]=newPlayer(i+1,begin,end);2425//设置特定的线程池,大小为526ExecutorService exe=Executors.newFixedThreadPool(PLAYER_AMOUNT);27for(Player p:plays)28exe.execute(p);//分配线程29System.out.println("Race begins!");30begin.countDown();31try{32end.wait();//等待end状态变为0,即为比赛结束33}catch(InterruptedException e) {34//TODO: handle exception35e.printStackTrace();36}finally{37System.out.println("Race ends!");38}39exe.shutdown();40}41}

接下来是Player类

注:countDown最好是在finally里面调用

1importjava.util.concurrent.CountDownLatch;234publicclassPlayerimplementsRunnable {56privateintid;7privateCountDownLatch begin;8privateCountDownLatch end;9publicPlayer(inti, CountDownLatch begin, CountDownLatch end) {10//TODO Auto-generated constructor stub11super();12this.id=i;13this.begin=begin;14this.end=end;15}1617@Override18publicvoidrun() {19//TODO Auto-generated method stub20try{21begin.await();//等待begin的状态为022Thread.sleep((long)(Math.random()*100));//随机分配时间,即运动员完成时间23System.out.println("Play"+id+"arrived.");24}catch(InterruptedException e) {25//TODO: handle exception26e.printStackTrace();27}finally{28end.countDown();//使end状态减1,最终减至029}30}31}

下面是张孝祥老师所举例子的程序代码和运行结果:

import java.util.concurrent.CountDownLatch;import java.util.concurrent.ExecutorService;import java.util.concurrent.Executors;

public class CountDownLatchTest {public static void main(String [] args){ExecutorService service = Executors.newCachedThreadPool();final CountDownLatch cdOrder = new CountDownLatch(1);final CountDownLatch cdAnswer = new CountDownLatch(3);for(int i=0;i<3;i++){Runnable runnable=new Runnable(){public void run(){try {System.out.println("线程"+Thread.currentThread().getName()+"正准备接受命令");cdOrder.await();System.out.println("线程"+Thread.currentThread().getName()+"已接受命令");Thread.sleep((long)(Math.random()*10000));System.out.println("线程"+Thread.currentThread().getName()+"回应命令处理结果");cdAnswer.countDown();} catch (InterruptedException e) {// TODO Auto-generated catch blocke.printStackTrace();}}};service.execute(runnable);}try {System.out.println("线程"+Thread.currentThread().getName()+"即将发布命令");cdOrder.countDown();System.out.println("线程"+Thread.currentThread().getName()+"已接受命令,正在等待结果");cdAnswer.await();Thread.sleep((long)(Math.random()*10000));System.out.println("线程"+Thread.currentThread().getName()+"已收到所有响应结果");} catch (InterruptedException e) {// TODO Auto-generated catch blocke.printStackTrace();}service.shutdown();}}运行结果:

线程pool-1-thread-1正准备接受命令线程pool-1-thread-2正准备接受命令线程pool-1-thread-3正准备接受命令线程main即将发布命令线程main已接受命令,正在等待结果线程pool-1-thread-2已接受命令线程pool-1-thread-1已接受命令线程pool-1-thread-3已接受命令线程pool-1-thread-2回应命令处理结果线程pool-1-thread-1回应命令处理结果线程pool-1-thread-3回应命令处理结果线程main已收到所有响应结果

当你能爱的时候就不要放弃爱

java线程中锁存器CountDownLatch的使用

相关文章:

你感兴趣的文章:

标签云: