您的位置:首页 > 编程语言 > Java开发

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

2016-09-10 21:51 225 查看
在实际开发过过程中,我们会经常遇见将一个“庞大”的任务拆分成多个子任务,各个子任务在独立的子线程中运行。待所有子线程的任务完成之后,在运行后续的业务,或者退出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 Main
run next process.
Thread-0run start.
Thread-1run start.
Thread-1run finished.
Thread-0run finished.
那么,我们有如下几种方式,可以实现以上的业务场景。一、JoinThread提供了让一个线程等待另一个线程完成的方法—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.
二、CountDownLatchCountDownLatch允许一个或多个线程等待其他线程完成操作。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工场”微信服务号,时刻关注我们的最新的技术讯息!(甭客气!尽情的扫描或者长按!)
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息