日积月累:Java等待子线程执行完毕,再执行后续逻辑

来源:互联网 发布:动漫小说软件 编辑:程序博客网 时间:2024/06/05 23:40
在实际开发过过程中,我们会经常遇见将一个“庞大”的任务拆分成多个子任务,各个子任务在独立的子线程中运行。待所有子线程的任务完成之后,在运行后续的业务,或者退出Main线程。代码如下:
WorkThread.java
public class WorkThread extends Thread {    @Override    public void run() {        try {            System.out.println(getName() + "run start.");            //模拟完成子任务执行的时间            sleep(1000);            System.out.println(getName() + "run finished.");        } catch (InterruptedException e) {            e.printStackTrace();        }    }}
Main.java
public class Main {    public static void main(String[] args) {        //启动两个子线程执行子任务        WorkThread workThread1 = new WorkThread();        WorkThread workThread2 = new WorkThread();        workThread1.start();        workThread2.start();                //运行后面的业务        System.out.println("run next process.");    }}
运行结果如下,在子线程启动后,Main线程就继续执行后面的逻辑,并不能满足我们的业务场景:
AppMain Mainrun next process.Thread-0run start.Thread-1run start.Thread-1run finished.Thread-0run finished.
那么,我们有如下几种方式,可以实现以上的业务场景。
一、Join
Thread提供了让一个线程等待另一个线程完成的方法—join()方法。当在某个程序执行流程中调用其它线程的join()方法时,调用线程将被阻塞,知道被join()方法加入的join线程执行完毕为止,在继续运行。
join()方法的实现原理是不停检查join线程是否存活,如果join线程存活则让当前线程永远等待。直到join线程完成后,线程的this.notifyAll()方法会被调用。
修改Main.java如下
public class Main {    public static void main(String[] args) {        WorkThread workThread1 = new WorkThread();        WorkThread workThread2 = new WorkThread();        workThread1.start();        workThread2.start();        //阻塞Main线程,执行子线程workThread1和workThread2,完毕后继续执行后续的逻辑        try {            workThread1.join();            workThread2.join();        } catch (InterruptedException e) {            e.printStackTrace();        }        System.out.println("run next process.");    }}
运行结果如下:
Thread-0run start.Thread-1run start.Thread-0run finished.Thread-1run finished.run next process.
二、CountDownLatch
CountDownLatch允许一个或多个线程等待其他线程完成操作。CountDownLatch的构造函数接收一个int类型的参数作为计数器,如果你想等待N个点完成,这里就传入N。当我们调用countDown方法时,N就会减1,await方法会阻塞当前线程,直到N变成0。
这里说的N个点,可以使用N个线程,也可以是1个线程里的N个执行步骤。

修改WorkThread.java和Main.java如下:
WorkThread.java
public class WorkThread extends Thread {    private CountDownLatch countDownLatch;    public WorkThread(CountDownLatch countDownLatch) {        this.countDownLatch = countDownLatch;    }    @Override    public void run() {        try {            System.out.println(getName() + "run start.");            sleep(1000);            //执行子任务完毕之后,countDown减少一个点            countDownLatch.countDown();            System.out.println(getName() + "run finished.");        } catch (InterruptedException e) {            e.printStackTrace();        }    }}
Main.java
public class Main {    public static void main(String[] args) {        //创建2个点的CountDownLatch对象        CountDownLatch countDownLatch = new CountDownLatch(2);                //将countDownLatch对象的引用传递给子线程里        WorkThread workThread1 = new WorkThread(countDownLatch);        WorkThread workThread2 = new WorkThread(countDownLatch);        workThread1.start();        workThread2.start();        try {            //调用await方法阻塞当前线程,等待子线程完成后在继续执行            countDownLatch.await();        } catch (InterruptedException e) {            e.printStackTrace();        }        System.out.println("run next process.");    }}
运行结果如下:
Thread-0run start.Thread-1run start.Thread-0run finished.Thread-1run finished.run next process.

新技术,新未来!欢迎大家关注“1024工场”微信服务号,时刻关注我们的最新的技术讯息!(甭客气!尽情的扫描或者长按!)

2 0
原创粉丝点击