Thread中yield()方法, join()方法- 理解記錄

yield()方法

/**
 * A hint to the scheduler that the current thread is willing to yield
 * its current use of a processor. The scheduler is free to ignore this
 * hint.(提示系統調度器當前線程愿意放棄其正在使用的處理器資源.調度器可以忽略
 這個提示.)
 *
 * <p> Yield is a heuristic attempt to improve relative progression
 * between threads that would otherwise over-utilise a CPU. Its use
 * should be combined with detailed profiling and benchmarking to
 * ensure that it actually has the desired effect.
 *
 * <p> It is rarely appropriate to use this method. It may be useful
 * for debugging or testing purposes, where it may help to reproduce
 * bugs due to race conditions. It may also be useful when designing
 * concurrency control constructs such as the ones in the
 * {@link java.util.concurrent.locks} package.
 */
public static native void yield();

  • A hint to the scheduler that the current thread is willing to yield its current use of a processor. The scheduler is free to ignore this hint.

翻譯: 提示系統調度器==當前線程==愿意放棄其正在使用的處理器資源.調度器可以忽略這個提示.(注:放棄正在使用的處理器資源也就表示一個線程將由運行狀態轉到就緒狀態,同時也說明此線程有可能會繼續被分配到處理器資源繼續執行)

靜態方法: 調用方式Thread.yield(); 從調用方式要理解的一個關鍵點是: 當前線程,那么這里的當前線程到底是哪個線程呢.比如我有代碼如下:

public class TestYield {
    public static void main(String[] args) throws InterruptedException {
        Thread thread = new Thread(){
            @Override
            public void run() {
                    try {
                        System.out.println("線程執行---");
                        sleep(3000);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
            }
        };
        System.out.println(System.currentTimeMillis());
        thread.start();
        Thread.yield();
        System.out.println(System.currentTimeMillis());
    }
}

當如上代碼執行的時候, Thread.yield()執行時,是哪個線程愿意放棄正在
使用的處理器資源呢,這里是主線程.也就是說Thread.yield()在哪個線程中被調用就
表示哪個線程愿意放棄處理器資源.


join()方法

join() : 當前線程暫停執行

/**
 * Waits for this thread to die.
 *
 * <p> An invocation of this method behaves in exactly the same
 * way as the invocation
 *
 * <blockquote>
 * {@linkplain #join(long) join}{@code (0)}
 * </blockquote>
 *
 * @throws  InterruptedException
 *          if any thread has interrupted the current thread. The
 *          <i>interrupted status</i> of the current thread is
 *          cleared when this exception is thrown.
 */
public final void join() throws InterruptedException {
    join(0);
}

join(long millis): 當前線程暫停執行,直到millis毫秒之后繼續執行

/**
 * Waits at most {@code millis} milliseconds for this thread to
 * die. A timeout of {@code 0} means to wait forever.
 *
 * <p> This implementation uses a loop of {@code this.wait} calls
 * conditioned on {@code this.isAlive}. As a thread terminates the
 * {@code this.notifyAll} method is invoked. It is recommended that
 * applications not use {@code wait}, {@code notify}, or
 * {@code notifyAll} on {@code Thread} instances.
 *
 * @param  millis
 *         the time to wait in milliseconds
 *
 * @throws  IllegalArgumentException
 *          if the value of {@code millis} is negative
 *
 * @throws  InterruptedException
 *          if any thread has interrupted the current thread. The
 *          <i>interrupted status</i> of the current thread is
 *          cleared when this exception is thrown.
 */
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(long millis, int nanos): 當前線程執行暫停, 直到millis+namos后繼續

/**
 * Waits at most {@code millis} milliseconds plus
 * {@code nanos} nanoseconds for this thread to die.
 *
 * <p> This implementation uses a loop of {@code this.wait} calls
 * conditioned on {@code this.isAlive}. As a thread terminates the
 * {@code this.notifyAll} method is invoked. It is recommended that
 * applications not use {@code wait}, {@code notify}, or
 * {@code notifyAll} on {@code Thread} instances.
 *
 * @param  millis
 *         the time to wait in milliseconds
 *
 * @param  nanos
 *         {@code 0-999999} additional nanoseconds to wait
 *
 * @throws  IllegalArgumentException
 *          if the value of {@code millis} is negative, or the value
 *          of {@code nanos} is not in the range {@code 0-999999}
 *
 * @throws  InterruptedException
 *          if any thread has interrupted the current thread. The
 *          <i>interrupted status</i> of the current thread is
 *          cleared when this exception is thrown.
 */
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) {
        throw new IllegalArgumentException(
                            "nanosecond timeout value out of range");
    }

    if (nanos >= 500000 || (nanos != 0 && millis == 0)) {
        millis++;
    }

    join(millis);
}

實例代碼:

public class TestJoin {
    public static void main(String[] args) throws InterruptedException {
        Thread thread = new Thread(){
            @Override
            public void run() {
                    try {
                        System.out.println("線程執行---");
                        sleep(3000);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
            }
        };
        System.out.println("開始:" + System.currentTimeMillis());
        thread.start();
        thread.join(3000);
        System.out.println("結束:" + System.currentTimeMillis());
    }
}

join()是實例方法, 只能在實例級別被調用, 那么在上述例子中,當執行thread.join()
方法時, 被暫停的是主線程還是thread線程呢? 結果是主線程被暫停. 也就是說被暫停
的線程還是調用執行這句代碼的線程.也就是說調用線程被暫停,而join()方法的所屬
實例繼續執行.如果join()方法不傳參數,那么主線程會等待直到thread線程執行完畢后
才會繼續執行,否則就是暫停傳入時間后繼續執行.
如果你想打斷這種暫停, 那么你可以在thread中調用notify(),notifyAll()方法來打斷.
但是就從注釋中我們也可以看出并不推薦在線程實例上條用notify()或者notifyAll()方法.

補充:從源碼中我們也可以看出join()方法其實是調用的Object的wait()方法來實現的,那么他又是在什么時候被notify的呢(我們知道被wait的線程必須被notify才會繼續執行).從注解(==As a thread terminates the

{@code this.notifyAll} method is invoked==)可知, 當一個線程終止時,他的notifyAll()方法會被調用

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容

  • 本文主要講了java中多線程的使用方法、線程同步、線程數據傳遞、線程狀態及相應的一些線程函數用法、概述等。 首先講...
    李欣陽閱讀 2,503評論 1 15
  • 該文章轉自:http://blog.csdn.net/evankaka/article/details/44153...
    加來依藍閱讀 7,381評論 3 87
  • 寫在前面的話: 這篇博客是我從這里“轉載”的,為什么轉載兩個字加“”呢?因為這絕不是簡單的復制粘貼,我花了五六個小...
    SmartSean閱讀 4,793評論 12 45
  • Java多線程學習 [-] 一擴展javalangThread類 二實現javalangRunnable接口 三T...
    影馳閱讀 2,994評論 1 18
  • 剛上一年級的女兒的詩 媽媽爸爸的愛。 媽媽的愛 象根藤 我象螞蟻上面爬 爸...
    精致典雅閱讀 331評論 0 2