在日常的编码中,Java并发编程是少不了的。尝试以下并发编程工具:今天,我将带领大家重温一下CountDownLatch这个工具类,这是一个神奇的工具。理解CountDownLatchCountDownLatch是一个同步工具类,用来协调多个线程之间的同步,或者起到线程间通信(非互斥)的作用。CountDownLatch使一个线程能够等待其他线程完成它们的工作,然后再继续。使用计数器实现。计数器的初始值是线程数。当每个线程完成其任务时,计数器的值将减一。当计数器的值为0时,表示所有线程都完成了一些任务,此时等待CountDownLatch的线程可以继续执行下一个任务。使用CountDownLatchCountDownLatch类使用起来非常简单。类位于:java.util.concurrent.CountDownLatch下面简单介绍一下它的构造方法和常用方法。构造方法CountDownLatch只提供了一种构造方法://count为初始计数值publicCountDownLatch(intcount){//...}常用方法//常用方法一:调用await()方法的线程会被挂起,它willwait直到计数值为0时继续执行//常用方法一:调用await()方法的线程会被挂起,等待计数值为0后才继续执行publicvoidawait()throwsInterruptedException{//...}//常用方法二:与await()类似,只是如果等待超时后计数值还没有变为0,则会继续执行publicbooleanawait(longtimeout,TimeUnitunit)throwsInterruptedException{//...}//常用方法3:计数值减1publicvoidcountDown(){//...}CountDownLatch应用场景我们考虑一个场景:用户购买商品下单成功后,我们会发送各种给用户的消息提醒用户表示购买成功,如发送邮件、微信、短信等。所有消息发送成功后,我们在后台记录一条消息,表示成功。当然,我们可以使用单线程一个一个地完成每个操作,如下图所示:但是这样效率会很低。如何解决单线程效率低的问题?当然是通过多线程。使用多线程也会遇到一个问题。在子线程消息发送之前,主线程可能已经打印了“Allmessageshavebeensent”,这在逻辑上肯定是不正确的。我们期望主线程在所有子线程发送消息后打印消息。如何实现?CountDownLatch可以解决这类问题。我们使用代码来实现上述需求。importjava.util.concurrent.*;publicclassOrderServiceDemo{publicstaticvoidmain(String[]args)throwsInterruptedException{System.out.println("mainthread:Successtoplaceanorder");intcount=3;CountDownLatchcountDownLatch=newCountDownLatch(count);Executorexecutor=Executors.newFixedThreadPool(count);executor.execute(newMessageTask("email",countDownLatch));executor.execute(newMessageTask("wechat",countDownLatch));executor.execute(newMessageTask("sms",countDownLatch));//主线程是blocked,等待所有子线程发送消息countDownLatch.await();//所有子线程发送完消息,计数器为0,主线程恢复System.out.println("mainthread:allmessagehasbeensent");}staticclassMessageTaskimplementsRunnable{privateStringmessageName;privateCountDownLatchcountDownLatch;publicMessageTask(StringmessageName,CountDownLatchcountDownLatch){this.messageName=messageName;this.countDownLatch=countDownLatch;}@Overridepublicvoidrun(){try{//线程发送消息System.out.println("Send"+messageName);try{TimeUnit.SECONDS.sleep(1);}catch(InterruptedExceptione){e.printStackTrace();}}finally{//发送消息计数器减1countDownLatch.countDown();}}}}程序运行结果:mainthread:SuccesstoplaceanorderSendemailSendwechatSendsmsmainthread:allmessagehasbeensent从运行结果可以看出,主线程是在所有子线程发送完消息后才打印,符合我们的预期。CountDownLatch是一次性的,计算器的值只能在构造函数中初始化一次。没有重新设置值的机制,当CountDownLatch用完后,就不能再使用了。
