1. 程式人生 > >Java中的join(),yield()解讀

Java中的join(),yield()解讀

前言:

多執行緒中讓執行緒等待的方法有很多種,下面我們就來分析一些這些方法的作用和區別.

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.所以輸出結果是:
這裡寫圖片描述