Loading [MathJax]/jax/output/CommonHTML/config.js
前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >专栏 >java CountDownLatch用法 主线程等待子线程执行完后再执行

java CountDownLatch用法 主线程等待子线程执行完后再执行

作者头像
IT云清
发布于 2022-05-07 08:36:57
发布于 2022-05-07 08:36:57
1K00
代码可运行
举报
文章被收录于专栏:IT云清IT云清
运行总次数:0
代码可运行
这里记录一下下面这种情况:主线程需要等待多个子线程执行完后再执行。

我们先看一下下面的场景:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
package com.java4all.mypoint;

import java.util.concurrent.CountDownLatch;

/**
 * Author: yunqing
 * Date: 2018/7/18
 * Description:线程测试
 * 测试点:主线程等待子线程全部执行完后再执行
 */
public class ThreadTest {

    public static void main(String[] args)throws Exception{
        System.out.println("主线程正在执行前:"+Thread.currentThread().getName());
        test3();
        System.out.println("主线程正在执行后:"+Thread.currentThread().getName());
    }

    public static void test3(){
        try {
            for (int i = 1 ;i <= 10;i ++){
                Thread.sleep(1000);
                new Thread(()->{
                    System.out.println("子线程正在执行:"+Thread.currentThread().getName());
                }).start();
            }
        }catch (Exception ex){
            ex.printStackTrace();
        }
    }

}

执行结果为:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
主线程正在执行前:main
子线程正在执行:Thread-0
子线程正在执行:Thread-1
子线程正在执行:Thread-2
子线程正在执行:Thread-3
子线程正在执行:Thread-4
子线程正在执行:Thread-5
子线程正在执行:Thread-6
子线程正在执行:Thread-7
子线程正在执行:Thread-8
主线程正在执行后:main
子线程正在执行:Thread-9

可以看到,子线程还没执行完时,主线程进来了。

1.使用CountDownLatch

示例如下,我们初始化一个CountDownLatch,值为10(子线程个数),然后每次一个子线程执行完后执行一下countDown(),代码示例如下:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
package com.java4all.mypoint;

import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit;

/**
 * Author: yunqing
 * Date: 2018/7/18
 * Description:线程测试
 * 测试点:主线程等待子线程全部执行完后再执行
 */
public class ThreadTest {

    /**初始化CountDownLatch,值为线程数量*/
    private static final CountDownLatch ctl = new CountDownLatch(10);
    
    public static void main(String[] args)throws Exception{
        System.out.println("主线程正在执行前:"+Thread.currentThread().getName());
        test3();
        ctl.await(20, TimeUnit.SECONDS);//最多等待20秒,不管子线程完没完
        System.out.println("主线程正在执行后:"+Thread.currentThread().getName());
    }


    public static void test3(){
        try {
            for (int i = 1 ;i <= 10;i ++){
                Thread.sleep(1000);
                new Thread(()->{
                    System.out.println("子线程正在执行:"+Thread.currentThread().getName());
                }).start();
                ctl.countDown();
            }
        }catch (Exception ex){
            ex.printStackTrace();
        }
    }

}

执行结果为:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
主线程正在执行前:main
子线程正在执行:Thread-0
子线程正在执行:Thread-1
子线程正在执行:Thread-2
子线程正在执行:Thread-3
子线程正在执行:Thread-4
子线程正在执行:Thread-5
子线程正在执行:Thread-6
子线程正在执行:Thread-7
子线程正在执行:Thread-8
子线程正在执行:Thread-9
主线程正在执行后:main
或者用java8之前的方式写:
线程类:
代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
package com.java4all.mypoint;

import java.util.concurrent.CountDownLatch;

/**
 * Author: yunqing
 * Date: 2018/7/23
 * Description:
 */
public class MyRunnable implements Runnable{

    public CountDownLatch countDownLatch;

    @Override
    public void run() {
        try {
            Thread.sleep(2000);
            System.out.println("子线程正在执行任务,当前线程为:"+Thread.currentThread().getName());
        }catch (InterruptedException inex){
            inex.printStackTrace();
        }finally {
            countDownLatch.countDown();
        }
    }


    public CountDownLatch getCountDownLatch() {
        return countDownLatch;
    }

    public void setCountDownLatch(CountDownLatch countDownLatch) {
        this.countDownLatch = countDownLatch;
    }
}
测试类:
代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
package com.java4all.mypoint;

import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit;

/**
 * Author: yunqing
 * Date: 2018/7/18
 * Description:线程测试
 * 测试点:主线程等待子线程全部执行完后再执行
 */
public class ThreadTest {

    /**初始化CountDownLatch,值为线程数量*/
    private static final CountDownLatch ctl = new CountDownLatch(10);

    public static void main(String[] args)throws Exception{
        System.out.println("主线程正在执行前:"+Thread.currentThread().getName());
        for(int i = 1;i <= 10;i ++){
            MyRunnable runnable = new MyRunnable();
            runnable.setCountDownLatch(ctl);
            Thread thread = new Thread(runnable);

            thread.start();
        }
        ctl.await(20, TimeUnit.SECONDS);//最多等待20秒,不管子线程完没完
        System.out.println("主线程正在执行后:"+Thread.currentThread().getName());
    }

}
结果为:
代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
主线程正在执行前:main
子线程正在执行任务,当前线程为:Thread-1
子线程正在执行任务,当前线程为:Thread-0
子线程正在执行任务,当前线程为:Thread-2
子线程正在执行任务,当前线程为:Thread-3
子线程正在执行任务,当前线程为:Thread-4
子线程正在执行任务,当前线程为:Thread-7
子线程正在执行任务,当前线程为:Thread-6
子线程正在执行任务,当前线程为:Thread-5
子线程正在执行任务,当前线程为:Thread-9
子线程正在执行任务,当前线程为:Thread-8
主线程正在执行后:main

附: 开启一个线程的其他写法:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
    /**jdk7匿名内部类的写法*/
    public static void test1(){
        new Thread(new Runnable() {
            @Override
            public void run() {
                System.out.println("aaaa");
            }
        }).start();
    }

    /**
	 * jdk8
	 * Runnable是个函数接口,可以利用jdk8的lambda来简写
     * 函数接口:是指内部只有一个抽象方法的接口
     * */
    public static void test2(){
        new Thread(()->{
            System.out.println("bbb");
        }).start();
    }
本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2018-07-23,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
编辑精选文章
换一批
带你了解控制线程执行顺序的几种方法
通常情况下,线程的执行顺序都是随机的,哪个获取到CPU的时间片,哪个就获得执行的机会。不过实际的项目中有时我们会有需要不同的线程顺序执行的需求。借助一些java中的线程阻塞和同步机制,我们往往也可以控制多个线程的执行顺序。
用户7634691
2020/08/10
1.9K0
同步屏障CyclicBarrier
CyclicBarrier,根据字面意思理解:循环屏障。屏障的意思:CyclicBarrier可以让一组线程到达某个屏障点时被阻塞,直到最后一个线程到达屏障点时,屏障才会放开,所有被屏障阻塞的线程才开始执行任务;循环:当所有线程被释放后,这个CyclicBarrier可以被重用。 有两个很常用的构造方法: 第一个: /** * Creates a new {@code CyclicBarrier} that will trip when the * given number
IT云清
2019/01/22
4610
JUC包下的CountDownLatch,CyclicBarrier,Semaphore
①.从CountDownLatch的设计来看,可以做汇总的操作,例如计算员工工资,这边启动多个线程同时计算等所有线程执行完毕之后,计算需要发放的总额 final ConcurrentHashMap<String, Integer> resultMap = new ConcurrentHashMap<String, Integer>(); final CountDownLatch c = new CountDownLatch(10); final Random r = new Random();
用户1215919
2018/02/27
5330
使用Java线程同步工具类CountDownLatch
java.util.concurrent.CountDownLatch是Java并发并发编程中的线程同步工具类,基于AQS(java.util.concurrent.locks.AbstractQueuedSynchronizer)实现。 CountDownLatch工具类主要应用在如下场景:等待一组线程执行完毕后继续执行后续操作。
编程随笔
2023/10/15
2010
Thread.join() 的使用
如果一个线程A执行了thread.join()语句,其含义是:当前线程A等待thread线程终止之后才 从thread.join()返回。线程Thread除了提供join()方法之外,还提供了join(long millis)和join(long millis,int nanos)两个具备超时特性的方法。这两个超时方法表示,如果线程thread在给定的超时 时间里没有终止,那么将会从该超时方法中返回。 在代码清单所示的例子中,创建了10个线程,编号0~9,每个线程调用前一个线程的 join()方法,也就是线程0结束了,线程1才能从join()方法中返回,而线程0需要等待main线程结 束。
爱明依
2019/03/12
8.7K0
多线程下ThreadLocalRandom用法[通俗易懂]
学习 ThreadLocalRandom 的时候遇到一些疑惑,为何使用它在多线程下会产生相同的随机数?
Java架构师必看
2022/03/12
8750
Java锁的分类_地锁怎么安装
  在笔者面试过程时,经常会被问到各种各样的锁,如乐观锁、读写锁等等,非常繁多,在此做一个总结。介绍的内容如下:
全栈程序员站长
2022/09/20
2520
CyclicBarrier使用方法
CyclicBarrier字面意思就是回环栅栏,通过它可以实现让一组线程等待至某个状态之后再全部同时执行。叫做回环是因为当所有等待线程都被释放以后,CyclicBarrier可以被重用。我们暂且把这个状态就叫做barrier,当调用await()方法之后,线程就处于barrier了。
benym
2022/07/14
9530
并发工具箱 concurrent包的原理分析以及使用
BlockingQueue 通常用于一个线程生产对象,而另外一个线程消费这些对象的场景。下图是对这个原理的阐述:
小勇DW3
2018/08/30
8630
并发工具箱 concurrent包的原理分析以及使用
CountDownLatch用法详解
CountDownLatch是一个同步工具类,它允许一个或多个线程一直等待,直到其他线程执行完后再执行。例如,应用程序的主线程希望在负责启动框架服务的线程已经启动所有框架服务之后执行。
全栈程序员站长
2022/09/14
9.2K0
CountDownLatch用法详解
并发编程系列之Semaphore用法简介
理解:就是要给令牌池,可获取信号量(令牌或者许可)、放入信号量。常用于控制并发的线程数,也可用于池类资源的访问控制。
SmileNicky
2021/11/30
7230
啰里吧嗦CountDownLatch
CountDownLatch是一个同步工具类,它允许一个或多个线程一直等待,直到其他线程的操作执行完后再执行
葫芦娃
2019/04/12
1.5K0
啰里吧嗦CountDownLatch
AQS-semaphore&CyclicBarrier&CountDownLatch源码学习
semaphore&cyclicbarrier&CountDownLatch的介绍
逍遥壮士
2023/02/28
2600
AQS-semaphore&CyclicBarrier&CountDownLatch源码学习
Java计数器之CountDownLatch、CyclicBarrier、Semaphore
在Java里面有几种可以用于控制线程状态的方法,如CountDownLatch计数器、CyclicBarrier循环栅栏、Sempahore信号量。下面就分别演示下他们的使用方法: CountDownLatch CountDownLatch可以实现多线程之间的计数器,并实现阻塞功能。比如某个任务依赖于其他的两个任务,只有那两个任务执行结束后,它才能执行。 import java.util.concurrent.CountDownLatch; public class CountDownLatchTest
用户1154259
2018/04/10
1.1K0
Java计数器之CountDownLatch、CyclicBarrier、Semaphore
基于Lock+Condition实现生产者消费者模式
package demo; import java.util.ArrayList; import java.util.List; import java.util.concurrent.locks.Condition; import java.util.concurrent.locks.Lock; import java.util.concurrent.locks.ReentrantLock; //产品仓库类 class Storage { private int maxSize; // 缓冲区
程裕强
2022/05/06
1930
基于Lock+Condition实现生产者消费者模式
【死磕Java并发】常用并发工具类详解
在前几篇文章中,我们讲到了线程、线程池、BlockingQueue 等核心组件,其实 JDK 给开发者还提供了比synchronized更加高级的线程同步组件,比如 CountDownLatch、CyclicBarrier、Semaphore、Exchanger 等并发工具类。
Java极客技术
2023/12/13
7370
【死磕Java并发】常用并发工具类详解
java一些常用并发工具示例
最近把《java并发编程实战》-Java Consurrency in Practice 重温了一遍,把书中提到的一些常用工具记录于此: 一、闭锁(门栓)- CountDownLatch 适用场景:多线程测试时,通常为了精确计时,要求所有线程都ready后,才开始执行,防止有线程先起跑,造成不公平,类似的,所有线程执行完,整个程序才算运行完成。 /** * 闭锁测试(菩提树下的杨过 http://yjmyzz.cnblogs.com/) * * @throws Inte
菩提树下的杨过
2018/01/18
5940
2.JUC线程高级-原子变量与CAS算法
执行完i++后为什么结果是10,原因是因为i++操作,jvm底层实际是分为以下三步:(读-改-写)
用户1212940
2022/04/13
2160
2.JUC线程高级-原子变量与CAS算法
ReentrantLock实现原理
建议和上一篇分享结合着看:深入理解AbstractQueuedSynchronizer
Java识堂
2019/08/13
4610
Java并发工具篇
前面我们介绍了 JUC 中的并发容器,它相当于一个同步容器的升级版,很大程度上提高了并发的性能
汤圆学Java
2021/05/12
4920
相关推荐
带你了解控制线程执行顺序的几种方法
更多 >
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档
本文部分代码块支持一键运行,欢迎体验
本文部分代码块支持一键运行,欢迎体验