-
在Thread类中一共有__3种__join函数的重载形式,都是非静态函数
public final void join() throws InterruptedException; public final synchronized void join(long millis) throws InterruptedException public final synchronized void join(long millis, int nanos) throws InterruptedException
(其实它们仨的根源函数都是第二种形式)
-
第二种形式的源码
public final synchronized void join(long millis) throws InterruptedException { long base = System.currentTimeMillis(); long now = 0; if (millis < 0) { throw new IllegalArgumentException("timeout value is negative"); } if (millis == 0) { while (isAlive()) { wait(0); //持有的是被等待线程t的锁, 那么被什么notify()或interrupt呢? } } else { while (isAlive()) { long delay = millis - now; if (delay <= 0) { break; } wait(delay); now = System.currentTimeMillis() - base; } } }
-
join函数的__作用__是:调用join函数的线程会进入等待状态(它等待的正是使用了join方法的线程实例,例如 在主线程中调用eatThread.join(), 那么主线程就会等待eatThread结束,才能再次重新运行状态或就绪状态)
-
带参数的join方法,代表当前线程只等待另一个线程 xx毫秒,然后它就又恢复到运行状态或就绪状态了;
不带参数的join方法,代表当前线程只能一直等,知道另一个线程完全结束才能恢复到运行状态或就绪状态
-
示例
class MyRunnable implements Runnable{ @Override public void run() { System.out.println("Thread started::"+Thread.currentThread().getName()); try { Thread.sleep(40000); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println("Thread ended::"+Thread.currentThread().getName()); } } class ThreadJoinExample { public static void main(String[] args) { Thread t1 = new Thread(new MyRunnable(), "t1"); Thread t2 = new Thread(new MyRunnable(), "t2"); Thread t3 = new Thread(new MyRunnable(), "t3"); t1.start(); //start second thread after waiting for 20 seconds or if it's dead try { t1.join(20000); } catch (InterruptedException e) { e.printStackTrace(); } t2.start(); //start third thread only when first thread is dead try { t1.join(); } catch (InterruptedException e) { e.printStackTrace(); } t3.start(); //let all threads finish execution before finishing main thread try { t1.join(); t2.join(); t3.join(); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println("All threads are dead, exiting main thread"); } }
这个示例的结果是
Thread started::t1 ---间隔大概20秒--> Thread started::t2 ---间隔大概20秒--> Thread ended::t1 ---几乎无间隔--> Thread started::t3 ---间隔大概20秒--> Thread ended::t2 ---间隔大概20秒--> Thread ended::t3 ---几乎无间隔--> All threads are dead, exiting main thread
说明
1° 在执行 t1.start()之前,程序只有一个主线程
2° 执行 t1.start()后,很快 t1线程开始,输出Thread started::t1,然后开始长达40秒的sleep
3° t1线程开始sleep以后,主线程继续向下执行,执行到t1.join(20000)时,代表主线程必须要等待20秒后或t1线程结束后,才能继续向下执行
4° 20秒过去了,t1线程没有结束,此时它已经睡了20秒,主线程的等待时间过去了,它可以继续向下执行 t2.start(),很快t2线程开始,输出Thread started::t2,然后也开始长达40秒的sleep
5° 现在t1和t2都在sleep,因此又会执行主线程,执行到t1.join()时,代表主线程只能等待t1结束才能向下执行
6° 由于在4°时t1线程已经睡了20秒,因此它又睡了20秒后,会输出Thread ended::t1,线程t1结束
7° 线程t1结束使得主线程可以继续向下执行,执行到t3.start()时,很快t3线程开始,输出Thread started::t3,然后也开始长达40秒的sleep
8° 现在的情况是,线程t2还要再睡20秒(因为有20秒的时间是和t1一起睡的),线程t3还要睡40秒,因此又到了主线程,主线程向下执行t1.join(),但由于t1线程已经结束,所以继续向下执行;主线程执行t2.join(),此时要等t2结束才能向下执行
9° 又过了大概20秒,t2线程睡醒,输出Thread ended::t2,线程t2结束,主线程可以向下执行t3.join(),等待t3线程结束
10° 又过了大概20秒,t3线程睡醒,输出Thread ended::t3,线程t3结束,主线程可以向下执行System.out.println(“All threads are dead, exiting main thread”),输出All threads are dead, exiting main thread。此时主线程也执行完毕,程序退出