一、问题描述
在程序设计中,可能存在这样的情景:主线程中存在一个子线程,子线程需要在执行完毕后为后续代码逻辑提供参数。但在代码执行时,子进程还没执行完毕,后续的代码已经开始执行了,这时候就会出现参数为空的异常,或是直接报错。
1 public class ThreadTest { 2 public static void main(String[] args) { 3 String str; 4 Thread thread = null; 5 thread = new Thread(new Runnable() { 6 @Override 7 public void run() { 8 while(true){ 9 System.out.println("Thread is running..."); 10 break; 11 } 12 } 13 }); 14 thread.start(); 15 16 System.out.println("Thread is finished..."); 17 } 18 }
执行结果:
因此,如何才能使得子进程执行完毕后才开始运行后续代码呢?
二、解决方法
1. join
Thread类提供了一个join( )方法,其原理是不断检查子进程是否执行完毕,当子进程未执行完成时,调用该子进程的进程被阻塞,直到子进程执行完毕后,再继续运行调用进程。
1 public class ThreadTest { 2 public static void main(String[] args) { 3 String str; 4 Thread thread = null; 5 thread = new Thread(new Runnable() { 6 @Override 7 public void run() { 8 while(true){ 9 System.out.println("Thread is running..."); 10 break; 11 } 12 } 13 }); 14 thread.start(); 15 try { 16 thread.join(); 17 } catch (InterruptedException e) { 18 e.printStackTrace(); 19 } 20 21 System.out.println("Thread is finished..."); 22 } 23 }
执行结果:
2. CountDownLatch
CountDownLatch允许一个或多个线程等待其他线程执行完毕后再运行。
- CountDownLatch的构造函数接收int类型的参数作为计数器,若要等待N个点再执行后续逻辑,就传入N。
- 这里的N可以是N个线程,也可以是N个执行步骤。
- 当我们调用countDown( )方法时,N会减一。
- 调用await( ) 方法来阻塞当前线程,直到N减为0。
1 public class ThreadTest { 2 public static void main(String[] args) { 3 CountDownLatch count = new CountDownLatch(2); 4 String str; 5 Thread thread1, thread2 = null; 6 thread1 = new Thread(new Runnable() { 7 @Override 8 public void run() { 9 System.out.println("Thread1" + " is running..."); 10 count.countDown(); 11 System.out.println("Thread1 " + " is finished..."); 12 } 13 }); 14 thread2 = new Thread(new Runnable() { 15 @Override 16 public void run() { 17 System.out.println("Thread2" + " is running..."); 18 count.countDown(); 19 System.out.println("Thread2" + " is finished..."); 20 } 21 }); 22 thread1.start(); 23 thread2.start(); 24 try { 25 count.await(); 26 } catch (InterruptedException e) { 27 e.printStackTrace(); 28 } 29 System.out.println("All is finished."); 30 } 31 }
执行结果: