线程的状态、进程的状态
一、線程的狀態
新建狀態、就緒狀態、阻塞狀態、死亡狀態。
1、新建狀態
新創建一個線程對象。
2、就緒狀態
線程對象創建后,其他線程調用了該對象的start()方法。該狀態的線程位于“可運行的線程池”中,變得可運行,只等待獲取CPU的使用權。即在就緒狀態的進程除了CPU之外,其他的運行所需資源都已全部獲得。
2.1、就緒狀態只是說有資格運行,調度程序沒有挑選到你,你就永遠是可運行狀態。
2.2、調用線程的start()方法,此線程進入就緒狀態。
2.3、當前線程sleep()方法結束,其他線程join()結束,等待用戶輸入完畢,某個線程拿到對象鎖,這些線程也將進入就緒狀態。
2.4、當前線程時間片用完了,調用當前線程的yeild()方法,當前線程進入就緒方法。
2.5、鎖池里的線程拿到對象鎖后,進入就緒狀態。
3、運行狀態
就緒狀態的線程獲取了CPU,執行程序代碼。
3.1、run()方法或main()方法結束后,線程就進入終止狀態。
3.2、當線程調用了自身的sleep()方法或其他線程的join()方法,進程讓出CPU,然后就會進入阻塞狀態(該狀態即停止當前線程,但并不釋放所占有的資源即調用sleep()方法后,線程不會釋放它的”鎖標志“)。當sleep()結束或join()結束后,該線程進入就緒狀態,繼續等待OS分配CPU時間片。典型的,sleep()被用在等待某個資源就緒的情形:測試發現條件不滿足后,讓線程阻塞一段時間后重新測試,直到條件滿足為止。
3.3、線程調用了yield方法,意思是放棄當前獲得的CPU時間片,回到就緒狀態,這是與其他進程處于同等競爭狀態,OS有可能會接著讓這個進程進入運行狀態,調用yield()的效果等價于調度程序認為該線程已執行了足夠的時間片從而需要轉到另一個線程。yield()只是使當前線程重新回到可執行狀態,所以執行yield()的線程有可能在進入到可執行狀態后馬上又被執行。
3.4、當線程進入就緒狀態,發現將要調用的資源被synchronized,獲取不到鎖標記,將會立即進入鎖池狀態,等待獲取鎖標記(這是的鎖池里也許已經有了其他線程在等待獲取所標記,這時它們處于隊列狀態,即先到先得),一旦線程獲得鎖標記后,就轉入就緒狀態,等待OS分配時間片。
3.5、suspend()和resume()方法:兩個方法配套使用,suspend()使得線程進入阻塞狀態,并且不會自動恢復,必須被對應的resume()調用,才能使得線程重新進入可執行狀態。典型的,suspend()和resume()被用在等待另一個線程產生的結果的情形:測試發現結果還沒有產生后,讓線程阻塞,另一個線程產生看了結果后,調用resume()使其恢復。
3.6、wait()和notify()方法:當線程調用wait()方法后會進入等待隊列(進入這個狀態會釋放所占有的所有資源,與阻塞狀態不同),進入這個狀態后,是不能自動喚醒的,必須依靠其他線程調用notify()或notifyAll()方法才能被喚醒(由于notify()只是喚醒一個線程,但我們不能確定具體喚醒的是哪一個線程,也許我們需要喚醒的線程不能夠被喚醒,因此在實際使用時,一般都用notifyAll()方法,喚醒所有線程),線程被喚醒后會進入鎖池,den
4、阻塞狀態
阻塞狀態是線程因為某種原因放棄CPU使用權,暫時停止運行。直到線程進入就緒狀態,才有機會轉到運行狀態。
阻塞的情況分三種:
4.1、等待阻塞:運行的線程執行wait()方法,該線程會釋放占用的所有資源,JVM會把該線程放入”等待池“中。進入這個狀態后,是不能自動喚醒的,必須依靠其他線程調用notify()或者notifyAll()方法才能被喚醒。
4.2、同步阻塞:運行的線程在獲取對象的同步鎖時,若該同步鎖被別的線程占用,則JVM會把該線程放入”鎖池“中。
4.3、其他阻塞:運行的線程執行了sleep()或join()方法,或者發出了i/o請求時,JVM會把該線程置為阻塞狀態。當sleep()狀態超時、join()等待線程終止或者超時、或者i/o處理完畢時,線程重新轉入就緒狀態。
4.4、當線程剛進入可運行狀態(注意,還沒運行),發現將要調用的資源被synchroniza(同步),獲取不到鎖標記,將會立即進入鎖池狀態,等待獲取鎖標記(這時的鎖池里也許已經有了其他線程在等待獲取鎖標記,這時它們處于隊列狀態,既先到先得),一旦線程獲得鎖標記后,就轉入就緒狀態,等待OS分配CPU時間片;
4.5. suspend() 和 resume()方法:兩個方法配套使用,suspend()使得線程進入阻塞狀態,并且不會自動恢復,必須其對應的resume()被調用,才能使得線程重新進入可執行狀態。典型地,suspend()和 resume() 被用在等待另一個線程產生的結果的情形:測試發現結果還沒有產生后,讓線程阻塞,另一個線程產生了結果后,調用 resume()使其恢復。?
4.6、wait()和 notify() 方法:當線程調用wait()方法后會進入等待隊列(進入這個狀態會釋放所占有的所有資源,與阻塞狀態不同),進入這個狀態后,是不能自動喚醒的,必須依靠其他線程調用notify()或notifyAll()方法才能被喚醒(由于notify()只是喚醒一個線程,但我們由不能確定具體喚醒的是哪一個線程,也許我們需要喚醒的線程不能夠被喚醒,因此在實際使用時,一般都用notifyAll()方法,喚醒有所線程),線程被喚醒后會進入鎖池,等待獲取鎖標記。
5、死亡狀態
線程執行完了或者因異常退出了run()方法,該線程結束生命周期。
二、進程的狀態
進程是系統進行資源分配和調度的基本單位。線程是CPU調度的基本單位。
一般來說,進程有三個狀態:
1、運行態
進程占用CPU,并在CPU上運行。
2、就緒態
進程已經具備運行條件,但是CPU還沒有分配過來。
3、阻塞態
進程因等待某件事發生而暫時不能運行。
上述的三種狀態之間轉換分為六種情況:
1、運行——>就緒:主要是進程占用CPU的時間過長,而系統分配給該進程占用CPU的時間是有限的;在采用搶先式優先級調度算法的系統中,當有更高優先級的進程要運行時,該進程就被迫讓出CPU,該進程便由執行狀態轉變為就緒狀態。
2、就緒——>運行:運行的進程的時間片用完,調度就轉到就緒隊列中選擇合適的進程分配CPU
3、運行——>阻塞:正在執行的進程因發生某等待事件而無法執行,則進程由執行狀態變為阻塞狀態,如發生了I/O請求
4、阻塞——>就緒:進程所等待的事件已經發生,就進入就緒隊列
以下兩種狀態是不可能發生的:
1、阻塞——>運行:即使給阻塞進程分配CPU,也無法執行,操作系統在進行調度時不會從阻塞隊列進行挑選,而是從就緒隊列中選取
2、就緒——>阻塞:就緒態根本就沒有執行,談不上進入阻塞態。
在一些系統中,又增加了一些新狀態,如掛起狀態,可運行狀態,深度睡眠狀態,淺度睡眠狀態,暫停狀態,僵死狀態。
1、可運行狀態:運行狀態和就緒狀態的合并,表示進程正在運行或準備運行,Linux 中使用TASK_RUNNING 宏表示可運行狀態。
2、淺度睡眠狀態:進程正在睡眠(被阻塞),等待資源的到來是喚醒,也可以通過其他進程信號或時鐘中斷喚醒,進入運行隊列。Linux 中使用TASK_INTERRUPTIBLE 宏表示此狀態。
3、深度睡眠狀態:其和淺度睡眠基本類似,但不可被其他進程信號或時鐘中斷喚醒。Linux 中使用TASK_UNINTERRUPTIBLE 宏表示此狀態。
4、暫停狀態:進程暫停執行接受某種處理。Linux 使用TASK_STOPPED 宏表示此狀態。
5、僵死狀態:進程已經結束但未釋放進程控制塊(PCB),Linux 使用TASK_ZOMBIE 宏表示此狀態。
掛起狀態:在執行狀態的進程通過掛起即可進入就緒狀態,如圖所示,就緒狀態和阻塞狀態都分為活動態和靜止態。由活動態向靜止態轉換就是通過掛起實現的。
引入掛起狀態的原因有:
1、終端用戶的請求。當終端用戶在自己的程序運行期間發現有可疑問題時,希望暫時使自己的程序靜止下來。亦即,使正在執行的進程暫停執行;若此時用戶進程正處于就緒狀態而未執行,則該進程暫不接受調度,以便用戶研究其執行情況或對程序進行修改。我們把這種靜止狀態稱為掛起狀態。
2、父進程請求。有時父進程希望掛起自己的某個子進程,以便考查和修改該子進程,或者協調各子進程間的活動。
3、負荷調節的需要。當實時系統中的工作負荷較重,已可能影響到對實時任務的控制時,可由系統把一些不重要的進程掛起,以保證系統能正常運行。
4、操作系統的需要。操作系統有時希望掛起某些進程,以便檢查運行中的資源使用情況或進行記賬。
總結
以上是生活随笔為你收集整理的线程的状态、进程的状态的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 北上广深的程序员,房子在向你们招手了!
- 下一篇: 非x面容解锁插件ios13_iOS13.