使當前執行緒等待,直到它被喚醒,通常是透過被通知或中斷,或直到經過一定的即時時間。
本身屬於一個Object 類,查看原始碼也可知:public class Object {
#查看其原始碼可知,一共有三個重載的方法,詳情原始碼如下:
//第一个重载函数 public final void wait() throws InterruptedException { wait(0L); } //第二个重载函数 public final native void wait(long timeoutMillis) throws InterruptedException; //第三个重载函数 public final void wait(long timeoutMillis, int nanos) throws InterruptedException { if (timeoutMillis < 0) { throw new IllegalArgumentException("timeoutMillis value is negative"); } if (nanos < 0 || nanos > 999999) { throw new IllegalArgumentException( "nanosecond timeout value out of range"); } if (nanos > 0 && timeoutMillis < Long.MAX_VALUE) { timeoutMillis++; } wait(timeoutMillis); }
具體實戰呼叫程式碼如下:
如果執行到了wait函數,在這4秒內,會釋放鎖定,並且暫停執行緒。如果這四秒內配合notify()可以喚醒並且得到鎖,如果沒有喚醒,等待其他來競爭。 4秒結束後,會預設自動釋放鎖定
目前執行緒在Thread.wait()等待過程中,如果Thread結束了,是可以自動喚醒的而且自動釋放鎖定
@Override public void run() { synchronized (a) { a.wait(4000); } }
join是Thread類別的方法
查看其原始碼,具體源碼如下,三個重載的方法
//第一个重载函数 public final synchronized void join(final long millis) throws InterruptedException { if (millis > 0) { if (isAlive()) { final long startTime = System.nanoTime(); long delay = millis; do { wait(delay); } while (isAlive() && (delay = millis - TimeUnit.NANOSECONDS.toMillis(System.nanoTime() - startTime)) > 0); } } else if (millis == 0) { while (isAlive()) { wait(0); } } else { throw new IllegalArgumentException("timeout value is negative"); } } //第二个重载函数 /*等待该线程死亡的时间最多为毫秒加纳秒。 如果两个参数都为0,则意味着永远等待。 这个实现使用了This的循环。 等待电话以this.isAlive为条件。 当一个线程终止this。 调用notifyAll方法。 建议应用程序不要使用wait、notify或notifyAll on Thread实例。 */ 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 > 0 && millis < Long.MAX_VALUE) { millis++; } join(millis); } //第三个重载函数 /*等待线程死亡。 此方法的调用与调用的行为完全相同 InterruptedException—如果任何线程中断了当前线程。 当抛出此异常时,当前线程的中断状态将被清除。 */ public final void join() throws InterruptedException { join(0); }
主要的時間參數邏輯如下:
小於0,拋出例外
等於0,join(A),判斷A是否存在,存在才執行運算。該執行緒執行wait(0)等待,等待A執行緒執行完後才可結束
#大於0,同上,只不過執行的是wait(long millis),等待時間結束後才可繼續執行操作
比較上一個wait函數
/*根据系统计时器和调度器的精度和准确性, 使当前执行的线程在指定的毫秒数内处于睡眠状态(暂时停止执行)。 线程不会失去任何监视器的所有权。*/ public static native void sleep(long millis) throws InterruptedException; /*导致当前执行的线程在指定的毫秒数加上指定的纳秒数 (取决于系统计时器和调度器的精度和准确性)内休眠(暂时停止执行)。 线程不会失去任何监视器的所有权。 */ public static void sleep(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 > 0 && millis < Long.MAX_VALUE) { millis++; } sleep(millis); }4. yield()查看yield()函數的原始碼,一個重載函數都是Thread類別的函數向調度器暗示當前執行緒願意放棄目前對處理器的使用。調度器可以忽略這個提示。 Yield是一種啟發式嘗試,旨在改善執行緒之間的相對進程,否則會過度使用CPU。它的使用應該與詳細的分析和基準測試相結合,以確保它實際上具有預期的效果。 使用這種方法很少是合適的。它可能用於調試或測試目的,在這些目的中,它可能有助於由於競爭條件而重新生成錯誤。在設計並發控制構造(如java.util.concurrent.locks套件中的構造)時,它可能也很有用。
public static native void yield();總的來說,yield函數的功能主要是:讓出CPU調度,暫停線程,但不能由使用者指定時間只能讓同優先級有執行機會5. 總結wait 暫停該線程,讓出cpu,釋放鎖定。 (Object類別)join暫停該線程,執行該線程之後才能回到自身的線程運行。 (Thread類別)sleep 暫停該線程,讓出cpu,不釋放鎖定。 (Thread類別)yield 暫停該線程,但是不能由使用者制定,只能讓同優先順序有執行機會。 (Thread類別)5.1 wait與join的區別看完以上的原始碼以及邏輯程式碼,再講講兩者的異同總的來說
wait | join | |
---|---|---|
Object類別 | Thread類別 | |
執行緒間通訊 | 排序,讓其串列通過 | |
必須要synchronized | #可以不用synchronized |
sleep(long mills):讓出CPU資源,但不會釋放鎖定資源。
看區別,主要是看CPU的運作機制:
它們的差異主要考慮兩點:1.cpu是否繼續執行、2.鎖是否釋放掉。
歸根到底:
wait,notify,notifyall 都是Object物件的方法,是一起使用的,用於鎖定機制,所以會釋放鎖定
而sleep是Thread類,跟鎖沒關係,不會釋放鎖定
但兩者都會讓出cpu資源
以上是Java常用的四個執行緒函數有哪些?的詳細內容。更多資訊請關注PHP中文網其他相關文章!