上篇咱們介紹了CountDownLatch,順便說到了Thread中的join方法!java
import java.util.concurrent.TimeUnit; /** * @author :jiaolian * @date :Created in 2021-02-28 21:43 * @description:join測試 * @modified By: * 公衆號:叫練 */ public class JoinTest { public static void main(String[] args) throws InterruptedException { Thread threadA = new Thread(()->{ try { TimeUnit.SECONDS.sleep(2); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println(Thread.currentThread().getName()+":想先執行"); },"線程A"); //開啓一個線程A threadA.start(); //主線程會持有子線程的鎖,子線程還沒開始主線程就阻塞了,等待子線程結束後通知; threadA.join(); System.out.println(Thread.currentThread().getName()+ "線程執行"); } }
如上代碼所示:在JoinTest開啓一個線程A,threadA調用join()方法,主線程會等待threadA執行完畢!也就是兩秒後,主線程執行最後一句話,運行結果以下圖所示!微信
咱們深刻源碼,join方法底層其實就是一個wait方法,但如今問題是:明明調用者是線程A,可阻塞的是mian線程,不該該阻塞的是threadA嗎?ide
咱們參照Thread中join源碼,將上面的代碼改造以下:測試
import java.util.concurrent.TimeUnit; /** * @author :jiaolian * @date :Created in 2021-02-28 21:43 * @description:join測試 * @modified By: * 公衆號:叫練 */ public class JoinCodeTest { public static void main(String[] args) throws InterruptedException { MyThread threadA = new MyThread("線程A"); //開啓一個線程A threadA.start(); //主線程會持有子線程的鎖,子線程還沒開始主線程就阻塞了,等待子線程結束後通知; threadA.join2(0); System.out.println(Thread.currentThread().getName()+ "線程執行"); } private static class MyThread extends Thread { public MyThread(String name) { super(name); } @Override public void run() { try { TimeUnit.SECONDS.sleep(2); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println(Thread.currentThread().getName()+":想先執行"); } //複製Thread源碼中的join方法測試阻塞的是線程A仍是main線程? public final synchronized void join2(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()) { //雖然調用者是線程A,但真正執行阻塞的是main線程! System.out.println(Thread.currentThread().getName()+"會阻塞"); wait(0); } } else { while (isAlive()) { long delay = millis - now; if (delay <= 0) { break; } wait(delay); now = System.currentTimeMillis() - base; } } } } }
如上代碼所示:MyThread繼承Thread,並複製了join源碼,將join修改爲join2,並在join2方法中增長了一個輸出語句,System.out.println(Thread.currentThread().getName()+"會阻塞")用來測試阻塞的是線程A仍是main線程,因此在JoinCodeTest的main方法中ThreadA是調用join2方法,spa
結果發現進入join2方法的線程是main線程。運行結果以下圖所示!線程
這裏能夠把join理解成一個普通方法!真正阻塞的不是調用者線程,而是當前正在執行的線程。blog
今天咱們介紹了join方法,特別是將源碼中代碼copy出來證實測試,相信整理出來但願能對你有幫助,寫的比不全,同時還有許多須要修正的地方,但願親們加以指正和點評,喜歡的請點贊加關注哦。點關注,不迷路,我是【叫練】公衆號,微信號【jiaolian123abc】邊叫邊練。繼承