Java 多線程基礎(九)join() 方法
- 2020 年 6 月 20 日
- 筆記
- Java 多線程基礎
Java 多線程基礎(九)join 方法
一、join() 方法介紹
join() 定義 Thread 類中的,作用是:把指定的線程加入到當前線程,可以將兩個交替執行的線程合併為順序執行的線程。如:線程B中調用了線程A的Join()方法,直到線程A執行完畢後,才會繼續執行線程B。
Thread 類中分別定義了: join() 、join(long millis) 和 join(long millis, int nanos) 三個方法。
①、join():等待線程t執行完畢。
②、join(long millis):等待 t 線程,等待時間是 millis 毫秒。
③、join(long millis, int nanos) :等待 t 線程,等待時間是 millis 毫秒 + nanos 納秒。
二、join() 示例
public class JoinThread { public static void main(String[] args) { try { Thread t1 = new MyThread("t1");// 新建線程t1 t1.start();// 啟動線程 t1.join(); // 將線程t1加入到主線程main中,並且主線程main()會等待它的完成 System.out.println(Thread.currentThread().getName() + " main end."); }catch(Exception e) { e.printStackTrace(); } } static class MyThread extends Thread{ public MyThread(String name) { super(name); } public void run() { System.out.println(Thread.currentThread().getName() + " run start."); for(int i = 0;i < 10000;i++) ; System.out.println(Thread.currentThread().getName() + " run end."); } } }
// 運行結果 t1 run start. t1 run end. main main end.
說明:
①、在「主線程main」中通過 new MyThread(“t1”) 新建「線程t1」。 接着,通過 t1.start() 啟動「線程t1」,並執行t1.join()。
②、執行t1.join()之後,「主線程main」會進入「阻塞狀態」等待t1運行結束。「子線程t1」結束之後,會喚醒「主線程main」,「主線程」重新獲取cpu執行權,繼續運行。
具體過程圖解:
三、join() 解析(基於JDK 1.8)
public final void join() throws InterruptedException { join(0); } 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); } } else { while (isAlive()) { long delay = millis - now; if (delay <= 0) { break; } wait(delay); now = System.currentTimeMillis() - base; } } } public final synchronized void join(long millis, int nanos) throws InterruptedException { if (millis < 0) { throw new IllegalArgumentException("timeout value is negative"); } if (nanos < 0 || nanos > 999999) { // 納秒值範圍在 (0 ~ 999999] throw new IllegalArgumentException("nanosecond timeout value out of range"); } if (nanos >= 500000 || (nanos != 0 && millis == 0)) { millis++; } join(millis); }
上面源碼是在Thread 類中定義的: join() 、join(long millis) 和 join(long millis, int nanos) 三個方法。
從上面代碼中可以看到,最主要的是 join(long millis) 方法,從該方法中可以發現:當傳遞的 millis == 0 時,會進入while(isAlive())循環;即只要子線程是活的,主線程就不停的等待。
問題:
雖然t1.join() 被調用的地方是發生在「main主線程」中,但是 t1.join() 是通過「子線程t1」去調用的 join()。那麼,join() 方法中的 isAlive() 應該是判斷「子線程t1」是不是 Alive 狀態;對應的 wait(0) 也應該是「讓子線程t1」等待才對。但如果是這樣的話,t1.join() 的作用怎麼可能是「讓主線程等待,直到子線程s完成為止」呢,應該是讓”子線程等待才對(因為調用子線程對象 t1 的 wait 方法嘛)”?
答案:
wait() 的作用是讓「當前線程」等待,而這裡的「當前線程」是指當前在CPU上運行的線程。所以,雖然是調用子線程的 wait() 方法,但是它是通過「主線程」去調用的;所以,休眠的是主線程,而不是「子線程」!