java实现多个子线程执行完毕后,再执行主线程

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




### 回答1: 下面是一个简单的java线程池应用的例:public class ThreadPoolExample { public static void main(String[] args) throws InterruptedException { ExecutorService executor = Executors.newFixedThreadPool(5); List<Future<String>> futureList = new ArrayList<>(); for (int i = 0; i < 10; i++) { Future<String> future = executor.submit(() -> { Thread.sleep(1000); return "执行成"; }); futureList.add(future); } for (Future<String> future : futureList) { System.out.println(future.get()); } System.out.println("所有线程都已成"); executor.shutdown(); } } ### 回答2: 在Java中,线程池可以通过Java的ExecutorService接口和ThreadPoolExecutor实现类来创建和管理。下面是一个简单的Java线程池的应用示例: ```java import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; public class ThreadPoolExample { public static void main(String[] args) { // 创建具有固定线程数的线程池 ExecutorService executor = Executors.newFixedThreadPool(3); // 启动3个线程进行工作 executor.submit(new WorkerThread("线程1")); executor.submit(new WorkerThread("线程2")); executor.submit(new WorkerThread("线程3")); // 关闭线程池 executor.shutdown(); // 等待所有线程执行成后输出一句话 while (!executor.isTerminated()) { // 等待线程池中的任务执行完毕 } System.out.println("所有线程已经执行成"); } static class WorkerThread implements Runnable { private String threadName; public WorkerThread(String threadName) { this.threadName = threadName; } @Override public void run() { System.out.println("线程" + threadName + "开始执行"); try { // 线程的任务 Thread.sleep(2000); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println("线程" + threadName + "执行成"); } } } ``` 该例中,我们创建了一个固定大小为3的线程池。然后通过submit方法提交了3个工作线程(WorkerThread)的任务给线程执行。每个工作线程执行任务时,会有2秒的休眠时间模拟实际的工作。 线程在提交了所有任务后,通过调用线程池的shutdown方法来关闭线程池。然后,在线程中通过一个循环,检查线程池中的任务是否全部执行成,直到线程池中所有任务都已成,才会输出一句话"所有线程已经执行成"。 这样就实现多个线程执行成后,线程输出一句话的需求。 ### 回答3: Java中的线程池是用来管理和复用线程的。下面是一个简单的使用线程池的例线程需要等待多个线程执行成之后输出一句话。 ```java import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; public class ThreadPoolExample { public static void main(String[] args) { // 创建一个固定大小为3的线程池 ExecutorService executor = Executors.newFixedThreadPool(3); // 创建3个线程并提交到线程执行 for (int i = 0; i < 3; i++) { executor.execute(new MyThread(i)); } // 关闭线程池 executor.shutdown(); // 线程等待所有线程执行成 while (!executor.isTerminated()) { // 等待线程执行成 } // 输出一句话 System.out.println("所有线程执行成"); } static class MyThread implements Runnable { private int id; public MyThread(int id) { this.id = id; } @Override public void run() { System.out.println("线程 " + id + " 开始执行"); // 线程执行的任务 try { Thread.sleep(1000); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println("线程 " + id + " 执行成"); } } } ``` 在这个例中,我们使用`Executors.newFixedThreadPool(3)`创建了一个固定大小为3的线程池。然后,我们创建了3个线程,并将它们提交到线程池中执行线程使用`executor.isTerminated()`方法来检查线程池中的所有任务是否都执行成了。如果没有,则线程等待。 当所有线程执行成后,线程输出一句话"所有线程执行成"。 注意:这里的线程池的大小为3,并行执行线程数量也为3,可以通过增加或减少线程池的大小来控制并发度。
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值