java实现多个子线程执行完毕后,再执行主线程
一、业务场景
1、 在做批量数据处理时,需执行多个存储过程。 执行1个存储过程,大概需10分钟,若一个一个的执行,将会耗时很久。 经过测试发现,数据库资源够用,具备同时执行多个存储过程的能力。
2、 在java中,到执行存储过程service时,异步开启子线程执行,存储过程service。 遇到问题是:主线程和子线程都在同时执行,这时,子线程结果还未执行完毕,主线程已经完毕,结果反馈给前端了。 ( 实际数据库中的存储过程还在执行中。。)
3、需求是: 主线程需等待子线程执行完毕后,才将结果返回给前端。
4、 大概业务代码如下:
public class MultiThread { public static void main(String[] args) { System.out.println("主线程开始执行...."); for (int i = 0; i < 3; i++) { new Thread(){ @Override public void run() { try { System.out.println(Thread.currentThread().getName()+" 开始执行存储过程.."); Thread.sleep(2000); System.out.println(Thread.currentThread().getName()+" 存储过程执行完毕..."); } catch (InterruptedException e) { e.printStackTrace(); } }; }.start(); } System.out.println("主线程执行完毕...."); } }
5、执行结果如下:
主线程开始执行....
主线程执行完毕....
Thread-2 开始执行存储过程..
Thread-0 开始执行存储过程..
Thread-1 开始执行存储过程..
Thread-2 存储过程执行完毕...
Thread-0 存储过程执行完毕...
Thread-1 存储过程执行完毕...
6、 很明显,该结果不符合业务需求,业务需求的是:
主线程开始执行....
Thread-0 开始执行存储过程..
...
Thread-2 存储过程执行完毕...
主线程执行完毕....
二、问题解决办法一 ( CountDownLatch) 实现
1、CountDownLatch: 是通过一个计数器来实现的,计数器的初始值为线程的数量。每当一个线程完成了自己的任务后,计数器的值就会减1。当计数器值到达0时,它表示所有的线程已经完成了任务,然后在闭锁上等待的线程就可以恢复执行任务。 (
CountDownLatch是什么
)
2、 代码实现如下:
public class MultiThreadToCountDownLatch { public static void main(String[] args) throws InterruptedException { //1、 创建CountDownLatch 对象, 设定需要计数的子线程数目 final CountDownLatch latch=new CountDownLatch(3); System.out.println("主线程开始执行...."); for (int i = 0; i < 3; i++) { new Thread(){ @Override public void run() { try { System.out.println(Thread.currentThread().getName()+" 开始执行存储过程.."); Thread.sleep(2000); System.out.println(Thread.currentThread().getName()+" 存储过程执行完毕..."); //2、子线程执行完毕,计数减1 latch.countDown(); } catch (InterruptedException e) { e.printStackTrace(); } }; }.start(); } System.out.println("等待子线程执行完毕..."); //3、 当前线程挂起等待 latch.await(); System.out.println("主线程执行完毕...."); } }
3、 执行结果如下:
主线程开始执行....
等待子线程执行完毕...
Thread-1 开始执行存储过程..
Thread-2 开始执行存储过程..
Thread-0 开始执行存储过程..
Thread-1 存储过程执行完毕...
Thread-2 存储过程执行完毕...
Thread-0 存储过程执行完毕...
主线程执行完毕....
4、 由执行结果可知,已经达到业务需求了。
三、其他实现方法补充
1、CyclicBarrier 和 Semaphore:
http://www.importnew.com/21889.html
2、 使用 join()及 CountDownLatch 和 CyclicBarrier 区别:
http://blog.csdn.net/u011277123/article/details/54015755