關於多執行緒中sleep、join、yield的區別
- 2019 年 10 月 3 日
- 筆記
好了、說了多執行緒,那就不得不說說多執行緒的sleep()、join()和yield()三個方法的區別啦
1、sleep()方法
/** * Causes the currently executing thread to sleep (temporarily cease * execution) for the specified number of milliseconds, subject to * the precision and accuracy of system timers and schedulers. The thread * does not lose ownership of any monitors. * 意思是說:當前正在執行的執行緒休眠(暫時停止執行)指定的毫秒數,具體取決於系統計時器和調度程式的精度和準確性。 該執行緒不會失去任何監視器的所有權。 * @param millis * the length of time to sleep 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 static native void sleep(long millis) throws InterruptedException;
其實主要的就是他是讓其他執行緒走,自己進行休眠,但是自己卻不會釋放對象鎖,也就是說,如果有同步鎖的時候,其他執行緒不能訪問共享數據。
注意該方法要捕獲異常 比如有兩個執行緒同時執行(沒有Synchronized),一個執行緒優先順序為MAX_PRIORITY,另一 個為MIN_PRIORITY,如果沒有Sleep()方法,只有高優先順序的執行緒執行完成後,低優先順序 的執行緒才能執行;但當高優先順序的執行緒sleep(5000)後,低優先順序就有機會執行了。 總之,sleep()可以使低優先順序的執行緒得到執行的機會,當然也可以讓同優先順序、高優先順序的 執行緒有執行的機會。
2、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. * 它是一種啟發式嘗試,用於改善執行緒之間的相對進展,否則會過度利用CPU。 它的使用應與詳細的分析和基準測試相結合,以確保它實際上具有所需的效果。 * <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();
yield() 這個方法從以上注釋可以看出,也是一個休眠自身執行緒的方法,同樣不會釋放自身鎖的標識,區別在於它是沒有參數的,即yield()方 法只是使當前執行緒重新回到可執行狀態,
所以執行yield()的執行緒有可能在進入到可執行狀態 後馬上又被執行,另外yield()方法只能使同優先順序或者高優先順序的執行緒得到執行機會,這也 和sleep()方法不同。
3、join() 方法
這個方法比較有意思,Thread的非靜態方法join()讓一個執行緒B“加入”到另外一個執行緒A的尾部。在A執行完畢之前, B不能工作。
/** * 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); // 調用了有參方法 }
/** * 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 {
保證當前執行緒停止執行,直到該執行緒所加入的執行緒完成為止。然而,如果它加入的執行緒沒有存活,則當前執行緒不需要停止。