線程基本狀態圖
圖中是線程運行的基本狀態:線程調用start()方法開始後,就進入到可運行狀態,隨着CPU的資源調度在運行和可運行之間切換;遇到阻塞則進入阻塞狀態。二三的狀態圖中只不過線程被阻塞的情況分爲很多種,後面的圖是細化說明。
New --> Runnable
當一個線程執行了start方法後,不代表這個線程就會立即被執行,只代表這個線程處於可運行的狀態,最終由OS的線程調度來決定哪個可運行狀態下的線程被執行。
Running --> Runnable
- Thread.yield()
- 一個線程一次被選中執行是有時間限制的,這個時間段叫做CPU的時間片,當時間片用完但線程還沒有結束時,這個線程又會變爲可運行狀態,等待OS的再次調度;
Running --> Blocked
- 在一個運行中的線程等待用戶輸入
- 調用Thread.sleep()
- 調用了其他線程的join()方法
Blocked --> Runnable
- 阻塞狀態的線程用戶輸入完畢
- sleep時間到
- join的線程結束
同步的線程狀態圖
Lock pool --> Runnable
當資源被一個線程訪問時,上鎖,其他線程就進入了一個鎖池(Lock pool);當鎖被釋放,其他線程獲得了鎖,就變爲可運行狀態。
加入線程間的相互作用
線程調用了wait()方法之後,釋放掉鎖,進入等待池(Wait pool) ;收到通知之後等待獲取鎖,獲取鎖之後纔可以運行。
線程被阻塞可能是由於下面五方面的原因:(《Thinking in Java》)
1.調用sleep(毫秒數),使線程進入睡眠狀態。在規定時間內,這個線程是不會運行的。
2.用suspend()暫停了線程的執行。除非收到resume()消息,否則不會返回“可運行”狀態。
3.用wait()暫停了線程的執行。除非線程收到notify()或notifyAll()消息,否則不會變成“可運行”狀態。
4.線程正在等候一些IO操作完成。
5.線程試圖調用另一個對象的“同步”方法,但那個對象處於鎖定狀態,暫時無法使用。
線程同步各個方法的區別
- Thread.yield()當前運行的線程變成可運行狀態。
- t2.join() 使得當前線程處於阻塞狀態直到t2線程執行完畢。
- Thread.sleep()使得當前線程處於阻塞狀態直到sleep的時間結束。
- wait、notify、notifyAll方法是Object類的方法,其調用環境必須有synchronized的同步塊中調用,否則會拋java.lang.IllegalMonitorStateException異常。