Java并发编程同步器CountDownLatch

作者:派大大大星? 时间:2022-10-17 18:59:34 

CountDownLatch

在日常开发中经常会遇到需要在主线程中开启多个线程去并行执行任务,并且主线程需要等待所有子线程执行完毕后再进行汇总的场景。在 CountDownLatch 出现之前般都使用线程的join()方法来实现这一点,但是 join 方法不够灵活,不能够满足不同场景的需要,所以 JDK 开发组提供了 CountDownLatch 这个类,我们前面介绍的例子使用 CoumtDownLatch 会更优雅。

使用CountDownLatch 的代码如下:

package LockSupportTest;

import java.util.concurrent.CountDownLatch;

public class JoinCountDownLatch {

private static volatile CountDownLatch countDownLatch = new CountDownLatch(2);

public static void main(String[] args) throws InterruptedException{

Thread threadOne = new Thread(new Runnable() {
           @Override
           public void run() {
               try {
                   Thread.sleep(1000);
                   System.out.println("child threadOne over!");
               } catch (InterruptedException e) {
                   e.printStackTrace();
               } finally {
                   countDownLatch.countDown();
               }
           }
       });

Thread threadTwo = new Thread(new Runnable() {
           @Override
           public void run() {
               try {
                   Thread.sleep(1000);
                   System.out.println("child threadOne over!");
               } catch (InterruptedException e) {
                   e.printStackTrace();
               } finally {
                   countDownLatch.countDown();
               }
           }
       });

threadOne.start();
       threadTwo.start();
       System.out.println("wait all child thread over!!!");
       countDownLatch.await();
       System.out.println("all child thread over!");
   }

}

Java并发编程同步器CountDownLatch

在如上代码中,创建了一个 CountDownLatch 实例,因为有两个子线程所以构造函数的传参为2。主线程调用countDownLatch.await()方法后会被阻塞。子线程执行完毕后调用 countDownLatch.countDown()方法让 countDownLatch 内部的计数器减1,所有子线程执行完毕并调用 countDown()方法后计数器会变为0,这时候主线程的await()方法才会返回。其实上面的代码还不够优雅,在项目实践中一般都避免直接操作线程,而是使用 ExceutorService线程池来管理,使用ExcsuIwsnise时传递的参数是 Runable 或者 Callable对象,这时候你没有办法直接调用这些线程的join()方法,这就需要选择使用CountDownLatch了。

将上面的代码修改为:

package LockSupportTest;

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

public class JoinCountDownLatch2 {

private static volatile CountDownLatch countDownLatch = new CountDownLatch(2);

public static void main(String[] args) throws InterruptedException{

ExecutorService executorService = Executors.newFixedThreadPool(2);
       executorService.submit(new Runnable() {
           @Override
           public void run() {
               try {
                   Thread.sleep(1000);
                   System.out.println("child threadOne over!");
               } catch (InterruptedException e) {
                   e.printStackTrace();
               } finally {
                   countDownLatch.countDown();
               }
           }
       });
       executorService.submit(new Runnable() {
           @Override
           public void run() {
               try {
                   Thread.sleep(1000);
                   System.out.println("child threadTwo over!");
               } catch (InterruptedException e) {
                   e.printStackTrace();
               } finally {
                   countDownLatch.countDown();
               }
           }
       });
       System.out.println("wait all child thread over!!!");
       countDownLatch.await();
       System.out.println("all child thread over!");
       executorService.shutdown();
   }

}

Java并发编程同步器CountDownLatch

最后总结一下CountDownLatch与join()的区别。一个区别是,调用一个子线程的join()方法后,该线程会一直被阻塞直到子线程运行完毕,而 CountDownLatch 则使用计数器来允许子线程运行完毕或者在运行中递减计数,也就是 CountDownLach 可以在子线程运行的任何时候让 await() 方法返回而不一定必须等到线程结東。另外,使用线程池来管理线程时一般都是直接添加 Runable 到线程池,这时候就没有办法再调用线程的 join 方法了,就是说 counDownLatch 相比 join 方法让我们对线程同步有更灵活的控制。

来源:https://juejin.cn/post/7083696858333184008

标签:Java,并发,编程,同步器,CountDownLatch
0
投稿

猜你喜欢

  • Java之如何关闭流

    2023-11-04 21:29:11
  • java中类加载与双亲委派机制详解

    2023-12-07 06:34:53
  • Android Parcleable接口的调用源码层分析

    2023-07-09 20:43:48
  • Java Http的基础概念了解

    2021-08-12 04:23:28
  • C#编程实现取整和取余的方法

    2023-09-09 22:19:26
  • android实现软件自动更新的步骤

    2022-12-27 00:48:17
  • Java java.sql.Timestamp时间戳案例详解

    2023-11-10 13:50:47
  • c#读写excel文件使用示例

    2021-08-27 03:02:53
  • java8中:: 用法示例(JDK8双冒号用法)

    2023-11-25 06:21:21
  • java ssm框架实现分页功能的示例代码(oracle)

    2021-10-31 01:14:40
  • Ubuntu安装jdk8常用方法流程解析

    2021-12-21 13:40:04
  • C#实现rar压缩与解压缩文件的方法

    2021-11-04 20:33:28
  • Java中new关键字和newInstance方法的区别分享

    2022-12-04 03:12:52
  • Java简单高效实现分页功能

    2022-05-24 13:56:02
  • Android 图片切换器(dp、sp、px) 的单位转换器

    2022-04-25 02:48:06
  • Java8中Optional类的使用说明

    2023-07-25 13:31:32
  • monkeyrunner之电脑安装驱动(5)

    2022-02-28 19:17:00
  • 3种C# 加载Word的方法

    2021-06-05 21:06:41
  • C#文件路径操作详细总结

    2021-06-06 04:07:41
  • Java连接ftp服务器实例代码

    2022-04-26 23:12:37
  • asp之家 软件编程 m.aspxhome.com