1. Thread.sleep(long) 和Thread.yield()都是Thread類的靜態方法,在調用的時候都是Thread.sleep(long)/Thread.yield()的方式進行調用。html
而join()是由線程對象來調用。java
2.wait()和notify()、notifyAll() 這三個方法都是java.lang.Object的方法! 面試
Object 是java.lang.Object,由於每天說Java是面向對象的,因此Object是全部Java對象的超類,都實現Object的方法;dom
它們都是用於協調多個線程對共享數據的存取,因此必須在Synchronized語句塊內使用這三個方法。前面說過Synchronized這個關鍵字用於保護共享數據,阻止其餘線程對共享數據的存取。可是這樣程序的流程就很不靈活了,如何才能在當前線程還沒退出Synchronized數據塊時讓其餘線程也有機會訪問共享數據呢?此時就用這三個方法來靈活控制。 socket
wait()方法使當前線程暫停執行並釋放對象鎖標誌,讓其餘線程能夠進入Synchronized數據塊,當前線程被放入對象等待池中。ide
當調用 notify()方法後,將從對象的等待池中移走一個任意的線程並放到鎖標誌等待池中,只有鎖標誌等待池中的線程可以獲取鎖標誌;若是鎖標誌等待池中沒有線程,則notify()不起做用。
notifyAll()則從對象等待池中移走全部等待那個對象的線程並放到鎖標誌等待池中。 this
看區別,主要是看CPU的運行機制:spa
它們的區別主要考慮兩點:1.cpu是否繼續執行、2.鎖是否釋放掉。線程
對於這兩點,首先解釋下cpu是否繼續執行的含義:cpu爲每一個線程劃分時間片去執行,每一個時間片時間都很短,cpu不停地切換不一樣的線程,以看似他們好像同時執行的效果。code
其次解釋下鎖是否釋放的含義:鎖若是被佔用,那麼這個執行代碼片斷是同步執行的,若是鎖釋放掉,就容許其它的線程繼續執行此代碼塊了。
明白了以上兩點的含義,開始分析sleep和wait:
sleep一段時間以後,每每線程會當即執行,可見cpu一直在爲此線程分配時間片,若是外層包有Synchronize,那麼此鎖並無釋放掉。所以sleep cpu繼續執行、鎖並無釋放掉;
wait,通常用於鎖機制中
(wait用於鎖機制,sleep不是,這就是爲啥sleep不釋放鎖,wait釋放鎖的緣由,sleep是線程的方法,跟鎖沒半毛錢關係,wait,notify,notifyall是一塊兒使用的,用於鎖機制),
確定是要釋放掉鎖的,由於notify並不會當即調起此線程,所以cpu是不會爲其分配時間片的,也就是說wait 線程進入等待池,cpu不分時間片給它,鎖釋放掉。
1.sleep:Thread類的方法,必須帶一個時間參數。會讓當前線程休眠進入阻塞狀態並釋放CPU(阿里面試題 Sleep釋放CPU,wait呢),提供其餘線程運行的機會且不考慮優先級,但若是有同步鎖則sleep不會釋放鎖即其餘線程沒法得到同步鎖
2.yield:讓出CPU調度,Thread類的方法,相似sleep只是不能由用戶指定暫停多長時間 ,而且yield()方法只能讓同優先級的線程有執行的機會。 yield()只是使當前線程從新回到可執行狀態,因此執行yield()的線程有可能在進入到可執行狀態後立刻又被執行。調用yield方法只是一個建議,告訴線程調度器個人工做已經作的差很少了,可讓別的相同優先級的線程使用CPU了,沒有任何機制保證採納。
3.wait:Object類的方法(notify()、notifyAll() 也是Object對象),必須放在循環體和同步代碼塊中,執行該方法的線程會釋放鎖,進入線程等待池中等待被再次喚醒(notify隨機喚醒,notifyAll所有喚醒,線程結束自動喚醒)即放入鎖池中競爭同步鎖
4.join:一種特殊的wait,當前運行線程調用另外一個線程的join方法,當前線程進入阻塞狀態直到另外一個線程運行結束等待該線程終止。 注意該方法也須要捕捉異常。
等待調用join方法的線程結束,再繼續執行。如:t.join();//主要用於等待t線程運行結束,若無此句,main則會執行完畢,致使結果不可預測。
import lombok.extern.slf4j.Slf4j; import java.util.Random; /** * 實現線上 * @author wucj * @date 2019-06-30 16:40 **/ @Slf4j public class ThreadAStatus implements Runnable{ private String name; private volatile int count; public ThreadAStatus(String name){ this.name = name; } @Override public void run() { log.info("線程{},執行次數:{}",name,++count); try{ log.info("線程{}開始執行,當前第:{}次",name,count); int maxCount = 10; for(int i=0;i<maxCount;i++){ log.info("線程{}開始執行,當前第:{}次",name,++count); int thisSleepSeconds = new Random().nextInt(5); log.info("線程:{},睡眠:{}秒",name,thisSleepSeconds); } }catch (Exception e){ log.error("線程:{}異常:{}",name,e); } } } import com.cjw.concurrent.thd.ThreadAStatus; import lombok.extern.slf4j.Slf4j; import org.junit.Test; /** * @author wucj * @date 2019-06-30 16:47 **/ @Slf4j public class ThreadStatusTest { @Test public void threadStatusAB(){ ThreadAStatus threadAStatus = new ThreadAStatus("A"); ThreadAStatus threadBStatus = new ThreadAStatus("B"); Thread threadA = new Thread(threadAStatus); Thread threadB = new Thread(threadBStatus); threadA.start(); threadB.start(); try{ for(int i=0;i<10;i++){ log.info("當前爲:{},執行第:{}次",Thread.currentThread().getName(),i); threadA.join(); threadB.join(); } Thread.sleep(100*1000); }catch (Exception e){ log.error("thread.join異常{}",e); } } } Connected to the target VM, address: '127.0.0.1:64837', transport: 'socket' 17:25:06.227 [main] INFO com.cjw.concurrent.ThreadStatusTest - 當前爲:main,執行第:0次 17:25:06.227 [Thread-1] INFO com.cjw.concurrent.thd.ThreadAStatus - 線程B,執行次數:1 17:25:06.227 [Thread-0] INFO com.cjw.concurrent.thd.ThreadAStatus - 線程A,執行次數:1 17:25:06.248 [Thread-0] INFO com.cjw.concurrent.thd.ThreadAStatus - 線程A開始執行,當前第:1次 17:25:06.247 [Thread-1] INFO com.cjw.concurrent.thd.ThreadAStatus - 線程B開始執行,當前第:1次 17:25:06.248 [Thread-0] INFO com.cjw.concurrent.thd.ThreadAStatus - 線程A開始執行,當前第:2次 17:25:06.248 [Thread-1] INFO com.cjw.concurrent.thd.ThreadAStatus - 線程B開始執行,當前第:2次 17:25:06.251 [Thread-1] INFO com.cjw.concurrent.thd.ThreadAStatus - 線程:B,睡眠:4秒 17:25:06.251 [Thread-0] INFO com.cjw.concurrent.thd.ThreadAStatus - 線程:A,睡眠:3秒 17:25:06.251 [Thread-1] INFO com.cjw.concurrent.thd.ThreadAStatus - 線程B開始執行,當前第:3次 17:25:06.251 [Thread-0] INFO com.cjw.concurrent.thd.ThreadAStatus - 線程A開始執行,當前第:3次 17:25:06.251 [Thread-1] INFO com.cjw.concurrent.thd.ThreadAStatus - 線程:B,睡眠:4秒 17:25:06.251 [Thread-0] INFO com.cjw.concurrent.thd.ThreadAStatus - 線程:A,睡眠:2秒 17:25:06.251 [Thread-1] INFO com.cjw.concurrent.thd.ThreadAStatus - 線程B開始執行,當前第:4次 17:25:06.251 [Thread-0] INFO com.cjw.concurrent.thd.ThreadAStatus - 線程A開始執行,當前第:4次 17:25:06.251 [Thread-0] INFO com.cjw.concurrent.thd.ThreadAStatus - 線程:A,睡眠:1秒 17:25:06.251 [Thread-1] INFO com.cjw.concurrent.thd.ThreadAStatus - 線程:B,睡眠:2秒 17:25:06.251 [Thread-0] INFO com.cjw.concurrent.thd.ThreadAStatus - 線程A開始執行,當前第:5次 17:25:06.251 [Thread-1] INFO com.cjw.concurrent.thd.ThreadAStatus - 線程B開始執行,當前第:5次 17:25:06.251 [Thread-1] INFO com.cjw.concurrent.thd.ThreadAStatus - 線程:B,睡眠:4秒 17:25:06.251 [Thread-1] INFO com.cjw.concurrent.thd.ThreadAStatus - 線程B開始執行,當前第:6次 17:25:06.251 [Thread-1] INFO com.cjw.concurrent.thd.ThreadAStatus - 線程:B,睡眠:4秒 17:25:06.251 [Thread-1] INFO com.cjw.concurrent.thd.ThreadAStatus - 線程B開始執行,當前第:7次 17:25:06.251 [Thread-1] INFO com.cjw.concurrent.thd.ThreadAStatus - 線程:B,睡眠:1秒 17:25:06.251 [Thread-1] INFO com.cjw.concurrent.thd.ThreadAStatus - 線程B開始執行,當前第:8次 17:25:06.251 [Thread-1] INFO com.cjw.concurrent.thd.ThreadAStatus - 線程:B,睡眠:3秒 17:25:06.251 [Thread-1] INFO com.cjw.concurrent.thd.ThreadAStatus - 線程B開始執行,當前第:9次 17:25:06.252 [Thread-1] INFO com.cjw.concurrent.thd.ThreadAStatus - 線程:B,睡眠:3秒 17:25:06.252 [Thread-1] INFO com.cjw.concurrent.thd.ThreadAStatus - 線程B開始執行,當前第:10次 17:25:06.252 [Thread-1] INFO com.cjw.concurrent.thd.ThreadAStatus - 線程:B,睡眠:2秒 17:25:06.252 [Thread-1] INFO com.cjw.concurrent.thd.ThreadAStatus - 線程B開始執行,當前第:11次 17:25:06.252 [Thread-1] INFO com.cjw.concurrent.thd.ThreadAStatus - 線程:B,睡眠:2秒 17:25:06.256 [Thread-0] INFO com.cjw.concurrent.thd.ThreadAStatus - 線程:A,睡眠:3秒 17:25:06.256 [Thread-0] INFO com.cjw.concurrent.thd.ThreadAStatus - 線程A開始執行,當前第:6次 17:25:06.256 [Thread-0] INFO com.cjw.concurrent.thd.ThreadAStatus - 線程:A,睡眠:0秒 17:25:06.256 [Thread-0] INFO com.cjw.concurrent.thd.ThreadAStatus - 線程A開始執行,當前第:7次 17:25:06.256 [Thread-0] INFO com.cjw.concurrent.thd.ThreadAStatus - 線程:A,睡眠:1秒 17:25:06.257 [Thread-0] INFO com.cjw.concurrent.thd.ThreadAStatus - 線程A開始執行,當前第:8次 17:25:06.257 [Thread-0] INFO com.cjw.concurrent.thd.ThreadAStatus - 線程:A,睡眠:2秒 17:25:06.257 [Thread-0] INFO com.cjw.concurrent.thd.ThreadAStatus - 線程A開始執行,當前第:9次 17:25:06.257 [Thread-0] INFO com.cjw.concurrent.thd.ThreadAStatus - 線程:A,睡眠:1秒 17:25:06.257 [Thread-0] INFO com.cjw.concurrent.thd.ThreadAStatus - 線程A開始執行,當前第:10次 17:25:06.257 [Thread-0] INFO com.cjw.concurrent.thd.ThreadAStatus - 線程:A,睡眠:1秒 17:25:06.257 [Thread-0] INFO com.cjw.concurrent.thd.ThreadAStatus - 線程A開始執行,當前第:11次 17:25:06.257 [Thread-0] INFO com.cjw.concurrent.thd.ThreadAStatus - 線程:A,睡眠:1秒 17:25:06.257 [main] INFO com.cjw.concurrent.ThreadStatusTest - 當前爲:main,執行第:1次 17:25:06.257 [main] INFO com.cjw.concurrent.ThreadStatusTest - 當前爲:main,執行第:2次 17:25:06.257 [main] INFO com.cjw.concurrent.ThreadStatusTest - 當前爲:main,執行第:3次 17:25:06.257 [main] INFO com.cjw.concurrent.ThreadStatusTest - 當前爲:main,執行第:4次 17:25:06.257 [main] INFO com.cjw.concurrent.ThreadStatusTest - 當前爲:main,執行第:5次 17:25:06.257 [main] INFO com.cjw.concurrent.ThreadStatusTest - 當前爲:main,執行第:6次 17:25:06.257 [main] INFO com.cjw.concurrent.ThreadStatusTest - 當前爲:main,執行第:7次 17:25:06.257 [main] INFO com.cjw.concurrent.ThreadStatusTest - 當前爲:main,執行第:8次 17:25:06.257 [main] INFO com.cjw.concurrent.ThreadStatusTest - 當前爲:main,執行第:9次
參考地址: