在讀到《java多線程編程核心技術(shù)》的3.2節(jié)“jion方法的使用”的時候立倍,看到如下代碼口注,便有了這篇總結(jié)的文章寝志。
TheadA.java:
public class ThreadA extends Thread {
private ThreadB b;
public ThreadA(ThreadB b) {
super();
this.b = b;
}
@Override
public void run() {
try {
synchronized (b) {
System.out.println("begin A ThreadName="
+ Thread.currentThread().getName() + " "
+ System.currentTimeMillis());
Thread.sleep(5000);
System.out.println(" end A ThreadName="
+ Thread.currentThread().getName() + " "
+ System.currentTimeMillis());
}
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
ThreadB.java:
public class ThreadB extends Thread {
@Override
synchronized public void run() {
try {
System.out.println("begin B ThreadName="
+ Thread.currentThread().getName() + " "
+ System.currentTimeMillis());
Thread.sleep(5000);
System.out.println(" end B ThreadName="
+ Thread.currentThread().getName() + " "
+ System.currentTimeMillis());
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
Main.java
public class Main{
public static void main(String[] args) {
try {
ThreadB b = new ThreadB();
ThreadA a = new ThreadA(b);
a.start();
b.start();
b.join(2000);
System.out.println(" main end "
+ System.currentTimeMillis());
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
jion方法的源代碼:
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;
}
}
}
如上的3個類舰攒,組成的這篇博文的主角悔醋。當(dāng)我們執(zhí)行main方法后芬骄,有幾率會出現(xiàn)如下順序的日志:
- 日志1:
begin A ThreadName=Thread-1 1545465206016
end A ThreadName=Thread-1 1545465211018
main end 1545465211019
begin B ThreadName=Thread-0 1545465211020
end B ThreadName=Thread-0 1545465216028
根據(jù)該日志的打印順序和結(jié)果來看:
- b.join(2000)處账阻,jion方法拿到鎖淘太,然后在jion方法里執(zhí)行到wait()時釋放鎖蒲牧。
- 線程a獲得鎖,TheadA類的run()中的sleep(5000)處阻塞松嘶,直到run()方法執(zhí)行完畢翠订,線程a釋放鎖尽超。在進(jìn)入run方法2s后梧躺,b.jion()方法在wait()處被喚醒燥狰,進(jìn)入激活隊(duì)列等待執(zhí)行龙致。
- b.jion(2000)和線程b競爭鎖目代,結(jié)果b.jion(2000)得到鎖,然后執(zhí)行wait()方法和面的代碼在讶,jion()方法執(zhí)行完构哺,然后釋放鎖曙强。
4.現(xiàn)在main線程和b線程異步執(zhí)行碟嘴,但是main線程的system.out.print()先于線程b的輸出執(zhí)行囊卜。
- 日志2:
begin A ThreadName=Thread-1 1545467317710
end A ThreadName=Thread-1 1545467322712
begin B ThreadName=Thread-0 1545467322714
main end 1545467322714
end B ThreadName=Thread-0 1545467327715
根據(jù)該日志的打印順序和結(jié)果來看:
- b.join(2000)處栅组,jion方法拿到鎖玉掸,然后在jion方法里執(zhí)行到wait()時釋放鎖排截。
- 線程a獲得鎖断傲,TheadA類的run()中的sleep(5000)處阻塞认罩,直到run()方法執(zhí)行完畢,線程a釋放鎖宦搬。在進(jìn)入run方法2s后间校,b.jion()方法在wait()處被喚醒憔足,進(jìn)入激活隊(duì)列等待執(zhí)行滓彰。
- b.jion(2000)和線程b競爭鎖,結(jié)果b.jion(2000)得到鎖弓候,然后執(zhí)行wait()方法和面的代碼菇存,jion()方法執(zhí)行完撰筷,然后釋放鎖毕籽。
- 現(xiàn)在main線程和b線程異步執(zhí)行井辆,但是main線程的system.out.print()后于線程b的輸出執(zhí)行杯缺。