1. 程式人生 > >java 主執行緒等待子執行緒執行完後再執行

java 主執行緒等待子執行緒執行完後再執行

這裡記錄一下下面這種情況:主執行緒需要等待多個子執行緒執行完後再執行。

我們先看一下下面的場景:

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