首页 > 编程语言 >java CountDownLatch用法 主线程等待子线程执行完后再执行

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

时间:2023-01-14 21:38:21浏览次数:38  
标签:正在 java Thread 完后 线程 CountDownLatch 执行 public


这里记录一下下面这种情况:主线程需要等待多个子线程执行完后再执行。

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

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();
}
}

}

执行结果为:

主线程正在执行前: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(),代码示例如下:

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();
}
}

}

执行结果为:

主线程正在执行前:main
子线程正在执行:Thread-0
子线程正在执行:Thread-1
子线程正在执行:Thread-2
子线程正在执行:Thread-3
子线程正在执行:Thread-4
子线程正在执行:Thread-5
子线程正在执行:Thread-6
子线程正在执行:Thread-7
子线程正在执行:Thread-8
子线程正在执行:Thread-9
主线程正在执行后:main

或者用java8之前的方式写:

线程类:
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;
}
}
测试类:
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());
}

}
结果为:
主线程正在执行前:main
子线程正在执行任务,当前线程为:Thread-1
子线程正在执行任务,当前线程为:Thread-0
子线程正在执行任务,当前线程为:Thread-2
子线程正在执行任务,当前线程为:Thread-3
子线程正在执行任务,当前线程为:Thread-4
子线程正在执行任务,当前线程为:Thread-7
子线程正在执行任务,当前线程为:Thread-6
子线程正在执行任务,当前线程为:Thread-5
子线程正在执行任务,当前线程为:Thread-9
子线程正在执行任务,当前线程为:Thread-8
主线程正在执行后:main

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

/**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();
}


标签:正在,java,Thread,完后,线程,CountDownLatch,执行,public
From: https://blog.51cto.com/u_15936016/6007791

相关文章

  • java Integer值比较
    所有相同类型的包装类对象之间的值比较,应该使用equals方法比较。先看个简单实例:publicstaticvoidmain(String[]args)throwsException{Integera=-121;......
  • 有了这份Java面试中的葵花宝典,让你面试起飞!!!
    HashMap面试题HashMap与HashTable的区别1.HashMap线程不安全HashTable线程是安全的采用synchronized2.HashMap允许存放key为nullHashTable不允许存放key为null3.......
  • 在Linxu云服务器中创建Java版MC服务器
    前言因为学校的课程里有华为云的Linux课程,课程发放有2佰代金券用于开启云服务器,现在课程基本结束了,代金券还剩一百五十多,之前已经试过和舍友开过MC服务器,那趁现在结课的时......
  • Java集合 - ConcurrentHashMap
    介绍ConcurrentHashMap技术是为了解决问题而生的,ConcurrentHashMap解决了多个线程同时操作一个HashMap时,可能出现的内部问题。当多个线程同时操作一个HashMap时,有可......
  • 第二章 线程管控
    第二章线程管控主要内容:启动线程,并通过几种方式为新线程指定运行代码等待线程完成和分离线程并运行唯一识别一个线程2.1线程的基本管控​ main函数其本声就是一......
  • Java集合 - ConcurrentHashMap
    介绍ConcurrentHashMap技术是为了解决问题而生的,ConcurrentHashMap解决了多个线程同时操作一个HashMap时,可能出现的内部问题。当多个线程同时操作一个HashMap时,有可......
  • Java 方法 实例 比较两个长方形的面积
    学习后,优化的,方法的目的一是可以重复被调用:packagecom.fqs.demo;publicclassMethodDemo2{publicstaticvoidmain(String[]args){//定义方法比......
  • Java判断是否是Windows系统
    在我们开发中,经常会读取一些本地文件,放到服务器肯定就要读取服务器的路径。本地win,远端服务器为Linux,所以就会进行系统判断等操作。//linux目录StringconfFileDir="......
  • java-打包
    方法0.使用package打包pom代码<build><plugins><plugin><groupId>org.springframework.boot</groupId>......
  • Java学习——酒店管理系统1
    酒店管理系统一、代码1.原始代码项目需求程序一启动,在控制台输出以下菜单用户选择1,2,3之后再一次展示菜单,可以一直选择用户选择4则提示谢谢您的使用程序运行......