场景:
package com.java4all.mypoint; import java.util.concurrent.CountDownLatch; 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; 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; 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(); }