转:https://blog.csdn.net/M983373615/article/details/97116131
java主线程等待所有子线程执行完毕在执行,其实在我们的工作中经常的用到,比如说主线程要返回一个响应用户的值,但这个值得赋值过程是由过个子线程来完成的(模拟一个实际开发的情景),所以主线程必须等待子线程执行完毕,再响应用户;否则,响应用户的是一个无意义的值。
那么如何确保所有的子线程执行完毕了。一般的有如下方法:
使用 ExecutorService线程池,等待所有任务执行完毕再执行主线程,awaitTermination。
我的解决办法如下:
awaitTermination(long timeout,TimeUnit unit)
请求关闭、发生超时或者当前线程中断,无论哪一个首先发生之后,都将导致阻塞,直到所有任务完成执行。
解决方案:
import java.util.concurrent.CountDownLatch; public class MyThread extends Thread { public MyThread(CountDownLatch threadSignal){ System.out.println("线程子启动,需要5秒...."); for (int i = 0; i < 5; i++) { System.out.print(i + 1+","); try { Thread.sleep(1000); } catch (InterruptedException e) { e.printStackTrace(); } } System.out.println("线程创建完毕....."); } @Override public void run() { for (int i = 0; i < 100; i++) { System.out.print("i = " + i+","); } System.out.println(); } }
import java.util.concurrent.*; public class Demo { public static void main(String[] args) throws InterruptedException { // 初始化countDown CountDownLatch threadSignal = new CountDownLatch(5); // 使用线程池 ExecutorService service = Executors.newScheduledThreadPool(5); MyThread myThread = new MyThread(threadSignal); for (int i=0;i<5;i++) { service.submit(myThread); } service.shutdown(); // service.isTerminated()判断子线程是否全部完成;完成 :true;没完成 :falese System.out.println("调用awaitTermination之前:"+service.isTerminated()); // 个人理解:如果service进行了shutdown操作,就查看子线程是否全部完成(也就是调用此方法),其中的参数相当于超时时间 service.awaitTermination(1,TimeUnit.HOURS); System.out.println("调用awaitTermination之后:"+service.isTerminated()); if (service.isTerminated()) { System.out.println("子线程执行完毕"); System.out.println("主线程开始"); } } }
线程子启动,需要5秒.... 1,2,3,4,5,线程创建完毕..... 睡两秒 i = 0,i = 1,i = 2,i = 3,i = 4,i = 5,i = 6,i = 7,i = 8,i = 9,i = 10,i = 11,i = 12,i = 13,i = 14,i = 15,i = 16,i = 17,i = 18,i = 19,i = 20,i = 21,i = 22,i = 23,i = 24,i = 25,i = 0,i = 26,i = 1,i = 27,i = 28,i = 0,i = 2,i = 0,i = 1,i = 2,i = 29,i = 30,i = 31,i = 32,i = 3,i = 3,i = 0,i = 1,i = 2,i = 3,i = 4,i = 5,i = 6,i = 7,i = 8,i = 9,i = 10,i = 11,i = 12,i = 13,i = 14,i = 15,i = 16,i = 17,i = 18,i = 19,i = 20,i = 1,i = 4,i = 5,i = 6,i = 7,i = 8,i = 9,i = 10,i = 11,i = 12,i = 13,i = 14,i = 15,i = 16,i = 17,i = 18,i = 19,i = 20,i = 4,i = 33,i = 5,i = 6,i = 7,i = 8,i = 9,i = 10,i = 11,i = 12,i = 13,i = 14,i = 15,i = 16,i = 17,i = 18,i = 19,i = 20,i = 21,i = 22,i = 23,i = 24,i = 25,i = 26,i = 21,i = 22,i = 23,i = 2,i = 21,i = 22,i = 3,i = 4,i = 5,i = 6,i = 24,i = 27,i = 25,i = 26,i = 34,i = 35,i = 36,i = 37,i = 38,i = 39,i = 40,i = 41,i = 42,i = 43,i = 44,i = 45,i = 46,i = 47,i = 48,i = 49,i = 50,i = 51,i = 52,i = 53,i = 54,i = 55,i = 56,i = 57,i = 58,i = 59,i = 60,i = 61,i = 62,i = 27,i = 28,i = 7,i = 8,i = 9,i = 10,i = 11,i = 12,i = 13,i = 23,i = 24,i = 25,i = 26,i = 27,i = 28,i = 29,i = 30,i = 31,i = 32,i = 33,i = 14,i = 15,i = 29,i = 28,i = 63,i = 29,i = 30,i = 31,i = 30,i = 16,i = 34,i = 17,i = 31,i = 32,i = 33,i = 34,i = 35,i = 36,i = 37,i = 38,i = 39,i = 40,i = 41,i = 42,i = 43,i = 44,i = 45,i = 46,i = 47,i = 64,i = 48,i = 32,i = 18,i = 35,i = 19,i = 33,i = 65,i = 49,i = 66,i = 34,i = 20,i = 36,i = 37,i = 38,i = 39,i = 40,i = 41,i = 21,i = 35,i = 36,i = 37,i = 38,i = 39,i = 40,i = 41,i = 42,i = 43,i = 44,i = 67,i = 50,i = 68,i = 45,i = 22,i = 42,i = 23,i = 46,i = 69,i = 70,i = 51,i = 71,i = 47,i = 24,i = 43,i = 25,i = 48,i = 72,i = 52,i = 73,i = 74,i = 75,i = 53,i = 49,i = 26,i = 44,i = 27,i = 50,i = 54,i = 76,i = 55,i = 51,i = 28,i = 45,i = 29,i = 52,i = 56,i = 77,i = 78,i = 57,i = 58,i = 59,i = 60,i = 53,i = 30,i = 31,i = 46,i = 47,i = 48,i = 49,i = 50,i = 51,i = 52,i = 53,i = 54,i = 55,i = 56,i = 57,i = 58,i = 59,i = 60,i = 61,i = 62,i = 63,i = 64,i = 65,i = 66,i = 67,i = 68,i = 69,i = 70,i = 71,i = 72,i = 73,i = 74,i = 75,i = 76,i = 77,i = 78,i = 32,i = 54,i = 61,i = 79,i = 62,i = 55,i = 33,i = 34,i = 35,i = 56,i = 57,i = 58,i = 79,i = 59,i = 36,i = 63,i = 80,i = 64,i = 37,i = 60,i = 80,i = 61,i = 38,i = 65,i = 81,i = 66,i = 39,i = 62,i = 81,i = 63,i = 40,i = 67,i = 82,i = 68,i = 69,i = 41,i = 64,i = 65,i = 82,i = 66,i = 42,i = 70,i = 83,i = 71,i = 43,i = 67,i = 83,i = 68,i = 44,i = 72,i = 84,i = 73,i = 45,i = 69,i = 84,i = 70,i = 46,i = 74,i = 85,i = 75,i = 47,i = 71,i = 85,i = 72,i = 48,i = 76,i = 86,i = 77,i = 49,i = 78,i = 73,i = 86,i = 74,i = 79,i = 50,i = 51,i = 87,i = 52,i = 80,i = 75,i = 87,i = 76,i = 81,i = 53,i = 88,i = 54,i = 82,i = 77,i = 88,i = 78,i = 83,i = 55,i = 89,i = 56,i = 84,i = 79,i = 85,i = 89,i = 86,i = 80,i = 81,i = 57,i = 90,i = 58,i = 82,i = 87,i = 90,i = 88,i = 83,i = 84,i = 59,i = 91,i = 60,i = 85,i = 89,i = 91,i = 90,i = 86,i = 61,i = 92,i = 62,i = 87,i = 91,i = 92,i = 92,i = 88,i = 63,i = 93,i = 64,i = 89,i = 93,i = 93,i = 94,i = 90,i = 65,i = 66,i = 67,i = 94,i = 95,i = 96,i = 97,i = 98,i = 99,i = 68,i = 91,i = 95,i = 96,i = 97,i = 98,i = 99, i = 94,i = 95,i = 96,i = 97,i = 98,i = 99, i = 92,i = 93,i = 94,i = 69,i = 70,i = 71,i = 72,i = 73,i = 74,i = 75,i = 76,i = 77,i = 78,i = 79,i = 80,i = 81,i = 82,i = 83,i = 84,i = 85,i = 86,i = 87,i = 88,i = 89, i = 90,i = 91,i = 92,i = 93,i = 94,i = 95,i = 96,i = 97,i = 95,i = 96,i = 97,i = 98,i = 98,i = 99, i = 99, 调用awaitTermination之前:true 调用awaitTermination之后:true 子线程执行完毕 主线程开始
其他:
1、 让主线程等待,或着睡眠几分钟。用Thread.sleep()或者TimeUnit.SECONDS.sleep(5);
如下:
package andy.thread.traditional.test; import java.util.concurrent.TimeUnit; /** * @author Zhang,Tianyou * @version 2014年11月21日 下午11:15:27 */ public class ThreadSubMain1 { public static void main(String[] args) { // TODO Auto-generated method stub for (int i = 0; i < 10; i++) { new Thread(new Runnable() { public void run() { try { Thread.sleep(1000); // 模拟子线程任务 } catch (InterruptedException e) { } System.out.println("子线程" + Thread.currentThread() + "执行完毕"); } }).start(); } try { // 等待全部子线程执行完毕 TimeUnit.SECONDS.sleep(5); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } System.out.println("主线执行。"); } }
子线程Thread[Thread-1,5,main]执行完毕 子线程Thread[Thread-3,5,main]执行完毕 子线程Thread[Thread-5,5,main]执行完毕 子线程Thread[Thread-7,5,main]执行完毕 子线程Thread[Thread-9,5,main]执行完毕 子线程Thread[Thread-0,5,main]执行完毕 子线程Thread[Thread-2,5,main]执行完毕 子线程Thread[Thread-4,5,main]执行完毕 子线程Thread[Thread-6,5,main]执行完毕 子线程Thread[Thread-8,5,main]执行完毕 主线执行。
此方主线程只是睡了5秒,但是不能保证全部的子线程执行完成,所以这儿的5秒只是一个估值
2 、使用Thread的join()等待所有的子线程执行完毕,主线程在执行
实现 如下
package andy.thread.traditional.test; import java.util.Vector; /** * @author Zhang,Tianyou * @version 2014年11月21日 下午11:15:27 */ public class ThreadSubMain2 { public static void main(String[] args) { // 使用线程安全的Vector Vector<Thread> threads = new Vector<Thread>(); for (int i = 0; i < 10; i++) { Thread iThread = new Thread(new Runnable() { public void run() { try { Thread.sleep(1000); // 模拟子线程任务 } catch (InterruptedException e) { } System.out.println("子线程" + Thread.currentThread() + "执行完毕"); } }); threads.add(iThread); iThread.start(); } for (Thread iThread : threads) { try { // 等待所有线程执行完毕 iThread.join(); } catch (InterruptedException e) { e.printStackTrace(); } } System.out.println("主线执行。"); } }
执行结果:
子线程Thread[Thread-1,5,main]执行完毕 子线程Thread[Thread-2,5,main]执行完毕 子线程Thread[Thread-0,5,main]执行完毕 子线程Thread[Thread-3,5,main]执行完毕 子线程Thread[Thread-4,5,main]执行完毕 子线程Thread[Thread-9,5,main]执行完毕 子线程Thread[Thread-7,5,main]执行完毕 子线程Thread[Thread-5,5,main]执行完毕 子线程Thread[Thread-8,5,main]执行完毕 子线程Thread[Thread-6,5,main]执行完毕 主线执行。