Java中的join(),yield()解讀
阿新 • • 發佈:2018-10-31
前言:
多執行緒中讓執行緒等待的方法有很多種,下面我們就來分析一些這些方法的作用和區別.
1. public static native void yield();
1.1 原始碼註釋翻譯:
(1). 向排程程器發起一個示意,表明當前執行緒樂意去放棄當前使用的處理器.排程器可以忽略這一提示.
(2). Yield是一種啟發式的嘗試,用於改進執行緒之間的相對進展,否則會過度使用CPU.它的使用應與詳細的分析和基準測試相結合,以確保它實際上達到期望的效果.
(3). Yield方法很少有場景去是和使用.它可能對除錯或測試目的很有用,它可能有助於重現因競爭條件而產生的錯誤.在設計併發控制結構(例如{@link java.util.concurrent.locks}包中的結構)時,它也可能很有用.
1.2 使用說明:
yield的方法一般不怎麼使用,當前線上程呼叫了yield方法後只是表示此樂意放棄處理器的使用權,排程器可以先去處理其他的程式.但是因為作業系統的排程室不確定的,並且執行緒是有優先順序的,有可能會A執行緒呼叫完yield()以後,等會A執行緒還是會被執行. 一般用於除錯程式和多執行緒之間呼叫的問題.
2. public final void join() throws InterruptedException
2.1 原始碼註釋:
(1). 等待這個執行緒死亡.
(2). 呼叫此方法的行為與呼叫完全相同
原始碼:
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;
}
}
}
可以看出join()呼叫的是join(long millis),join(0)表示永遠等待,直到該執行緒結束.join(long millis)的判斷條件是該執行緒是否存活.存活則呼叫wait方法.(wait是object類的方法)
2.2 實踐例子:
public class JoinTest {
public static void main(String[] args) throws InterruptedException {
Thread a = new Thread(
()->{
System.out.println(Thread.currentThread().getName() + "啟動");
System.out.println(Thread.currentThread().getName() + "結束");
}
);
Thread b = new Thread(
()->{
System.out.println(Thread.currentThread().getName() + "啟動");
try {
System.out.println(Thread.currentThread().getName() + "sleep 3 秒");
Thread.currentThread().sleep(3000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName() + "結束");
}
);
b.start();
// b.join();
a.start();
}
}
這個程式當b沒有join時,b肯定是後執行完畢,因為b休眠了2秒.
輸出結果:
如果加上了join,則main的執行緒會等待b執行完畢以後,在繼續往下執行a.所以輸出結果是: