線程的狀態轉換是線程控制的基礎。線程狀態總的能夠分爲五大狀態:分別是生、可運行、運行、等待|阻塞|睡眠、死。java
一、新狀態:線程對象已經建立,尚未在其上調用start()方法。多線程
二、可運行狀態:當線程有資格運行,但調度程序尚未把它選定爲運行線程時線程所處的狀態。當start()方法調用時,線程首先進入可運行狀態,在線程運行以後或者阻塞、等待或睡眠狀態回來後,也返回到能夠運行狀態。ide
三、運行狀態:線程調度陳旭從可運行池中選擇一個線程做爲當前線程時線程所處的狀態。這也是線程進入運行狀態的惟一一種方式。post
四、等待|阻塞|睡眠狀態:這是線程有資格運行時它所處的狀態。實際上這是那個狀態能夠合爲一種,this
其共同點爲:線程仍舊還活着。可是當前沒有條件運行。換句話說,它是可運行的,可是若是某件事情出現,他可能返回到可運行狀態。spa
五、 死亡狀態:當線程的run()方法完成時就能夠認爲線程死去了。這個線程對象或許是活的,可是,它已經不是一個單獨可執行的線程。線程一旦死亡,就不能復 生。若是在一個死去的線程上調用start()方法,會拋出java.lang.IllegalThreadStateException異常。線程
2、阻止線程執行設計
對於線程的阻止,考慮一下三個方面,不考慮IO阻塞的狀況:對象
睡眠、等待blog
須要一個對象的鎖定而被阻塞。
一、睡眠 sleep()
Thread.sleep(long millis) 和 Thread.sleep(long millis, int nanos)靜態方法強制當前正在執行的線程睡眠(暫停執行),以"減慢線程"。當線程睡眠時,它入睡在某個地方,在甦醒以前不會返回到可運行狀態。當睡 覺時間到期,則返回到可運行狀態。
線程睡眠的緣由:線程執行太快,或者須要強制進入下一輪,由於Java規範不保證合理的輪換。
睡眠的實現:調用靜態方法便可。
睡眠的位置:爲了讓其餘線程有機會執行,能夠將Thread.sleep()的調用放到線程run()方法以內,這樣才能保證線程執行過程當中會睡眠。
例如:
三、Thread.yield()方法
Thread.yield() 方法做用是:暫停當前正在執行的線程對象,並執行其餘線程。yield應該作的是讓當前運行的線程回到可運行狀態,以容許具備相同優先級的其餘線程得到運 行機會。所以,使用yield的目的是讓相同優先級的線程之間能適當的輪轉執行。可是,實際中沒法保證yield達到讓步目的,由於讓步的線程還有可能被 線程調度程序再次選中。
結論:yield()從未致使線程轉到等待|睡眠|阻塞狀態。在大多數狀況下,yield()將致使線程從運行狀態轉到可運行狀態,可是可能沒有效果。
四、join()方法
Thread的非靜態方法join()讓一個線程B加入到另一個線程A的尾部。在A執行完畢以前,B不能執行。
線程t執行完畢後線程t2方能執行。
小結:
到目前爲止,線程離開運行狀態的3中方法:
一、調用Thread.sleep():使當前線程睡眠至少多少毫秒(儘管它可能在指定的時間以前被調度程序中斷)。
二、調用Thread.yield():不能保障太多事情,儘管一般它會讓當前運行線程回到可運行性狀態,使得有相同優先級的線程有機會執行。
三、調用join()方法:保證當前線程中止執行,直到該線程所加入的線程完成爲止,然而,若是它加入的線程沒有存活,則當前線程不須要中止。
除了以上三種方式外,還有下面幾種特殊狀況可能使線程離開運行狀態:
一、線程的run()方法正常執行完畢。
二、在對象上調用wait()方法(不是在線程上調用)。
三、線程不能在對象上得到鎖定,它正試圖運行該對象上的方法代碼。
四、線程調度程序能夠決定將當前運行狀態移動到可運行狀態,以便另外一個線程得到運行機會,而不須要任何理由。
第一種解釋:
功能差很少,都用來進行線程控制,他們最大本質的區別是:sleep()不釋放同步鎖,wait()釋放同步縮.
還有用法的上的不一樣是:sleep(milliseconds)能夠用時間指定來使他自動醒過來,若是時間不到你只能調用interreput()來強行打斷;wait()能夠用notify()直接喚起.
第二種解釋:
sleep是Thread類的靜態方法。sleep的做用是讓線程休眠制定的時間,在時間到達時恢復,也就是說sleep將在接到時間到達事件事恢復線程執行,例如:
try{
System.out.println("I'm going to bed");
Thread.sleep(1000);
System.out.println("I wake up");
}
catch(IntrruptedException e) {
}
wait是Object的方法,也就是說能夠對任意一個對象調用wait方法,調用wait方法將會將調用者的線程掛起,直到其餘線程調用同一個對象的notify方法纔會從新激活調用者,例如:
//Thread 1
try{
obj.wait();//suspend thread until obj.notify() is called
}
catch(InterrputedException e) {
}
第三種解釋:
這二者的施加者是有本質區別的.
sleep()是讓某個線程暫停運行一段時間,其控制範圍是由當前線程決定,也就是說,在線程裏面決定.比如如說,我要作的事情是 "點火->燒水->煮麪",而當我點完火以後我不當即燒水,我要休息一段時間再燒.對於運行的主動權是由個人流程來控制.
而 wait(),首先,這是由某個肯定的對象來調用的,將這個對象理解成一個傳話的人,當這我的在某個線程裏面說"暫停!",也是 thisOBJ.wait(),這裏的暫停是阻塞,仍是"點火->燒水->煮飯",thisOBJ就比如一個監督個人人站在我旁邊,原本該線 程應該執行1後執行2,再執行3,而在2處被那個對象喊暫停,那麼我就會一直等在這裏而不執行3,但正個流程並無結束,我一直想去煮飯,但還沒被容許, 直到那個對象在某個地方說"通知暫停的線程啓動!",也就是thisOBJ.notify()的時候,那麼我就能夠煮飯了,這個被暫停的線程就會從暫停處 繼續執行.
其實二者均可以讓線程暫停一段時間,可是本質的區別是一個線程的運行狀態控制,一個是線程之間的通信的問題
在java.lang.Thread類中,提供了sleep(),
而java.lang.Object類中提供了wait(), notify()和notifyAll()方法來操做線程
sleep()能夠將一個線程睡眠,參數能夠指定一個時間。
而wait()能夠將一個線程掛起,直到超時或者該線程被喚醒。
wait有兩種形式wait()和wait(milliseconds).
sleep和wait的區別有:
1,這兩個方法來自不一樣的類分別是Thread和Object
2,最主要是sleep方法沒有釋放鎖,而wait方法釋放了鎖,使得其餘線程可使用同步控制塊或者方法。
3,wait,notify和notifyAll只能在同步控制方法或者同步控制塊裏面使用,而sleep能夠在
任何地方使用
synchronized(x){
x.notify()
//或者wait()
}
4,sleep必須捕獲異常,而wait,notify和notifyAll不須要捕獲異常