什么是多線程
?????java對多線程編程提供了內(nèi)置支持戚篙。多線程程序包含同時運(yùn)行的兩個或多個部分。這種程序的每個部分被稱為一個線程挽封,每個線程定義了單獨(dú)的執(zhí)行路徑已球。因此,多線程是特殊形式的多任務(wù)處理辅愿。
?????多任務(wù)處理有兩種不同的類型:基于進(jìn)程的多任務(wù)處理和基于線程多多任務(wù)處理智亮。
進(jìn)程和線程區(qū)別
?????基于進(jìn)程的多任務(wù)處理就是允許計(jì)算機(jī)同時運(yùn)行兩個或更多個程序特性。例如点待,基于進(jìn)程的多任務(wù)處理可以運(yùn)行java編譯器的同時使用文本編輯器或?yàn)g覽網(wǎng)站阔蛉。在基于進(jìn)程的多任務(wù)處理中,程序是調(diào)度程序能夠調(diào)度的最小單元癞埠。
?????基于線程的多任務(wù)環(huán)境中状原,最小的可調(diào)度代碼單元是線程,這意味著單個程序可以同時執(zhí)行兩個或多個任務(wù)苗踪。例如颠区,在文本編輯器可以在打印的同時格式化文本,只要兩個動作是通過兩個獨(dú)立的線程執(zhí)行即可通铲。
因此毕莱,基于進(jìn)程的多任務(wù)處理“大局”,而基于線程的多任務(wù)處理“細(xì)節(jié)”颅夺。
java線程模型
?????java運(yùn)行時系統(tǒng)在許多方面依賴于線程朋截,并且所有類庫在設(shè)計(jì)時都考慮了多線程。事實(shí)上吧黄,java通過利用線程使得整個環(huán)境能夠異步執(zhí)行部服。有助于通過防止浪費(fèi)CPU時鐘周期來提高效率。
?????通常拗慨,在單線程環(huán)境中廓八,當(dāng)線程因?yàn)榈却承┵Y源而阻塞(即掛起執(zhí)行)時,整個程序會停止運(yùn)行赵抢。
?????java多線程的優(yōu)點(diǎn)消除了主循環(huán)/論詢機(jī)制瘫想。可以暫停一個線程而不會停止程序的其他部分昌讲。也就是說国夜,當(dāng)java程序中的線程堵塞時,只有被阻塞的線程會停止短绸,所有其他線程仍將繼續(xù)執(zhí)行车吹。
線程的多種形態(tài)
?????運(yùn)行(running)狀態(tài):只要獲得CPU時間就準(zhǔn)備運(yùn)行。運(yùn)行的線程可以被掛起(suspended)醋闭,這會臨時停止線程的活動窄驹。掛起的線程可以被恢復(fù)(resumed),從而允許線程從停止處恢復(fù)執(zhí)行证逻。當(dāng)?shù)却Y源時乐埠,線程會被阻塞(blocked)。
在任何時候,都可以終止線程丈咐,這會立即停止線程的執(zhí)行瑞眼。線程一旦終止,就不可能再恢復(fù)棵逊。
線程優(yōu)先級
?????java為每個線程都指定了優(yōu)先級伤疙,優(yōu)先級決定了相對于其他線程應(yīng)當(dāng)如何處理某個線程。線程優(yōu)先級的一些整數(shù)辆影,它們指定了一個線程相對于另一個線程的優(yōu)先程度徒像。優(yōu)先級的絕對數(shù)值沒有意義;如果只有一個線程在運(yùn)行,優(yōu)先級高的線程不會比優(yōu)先級低的線程運(yùn)行的快蛙讥。反而锯蛀,線程的優(yōu)先級用于決定何時從一個運(yùn)行的線程切換到下一個,這稱為上下文切換次慢。
?????決定上下文切換發(fā)生時機(jī)的規(guī)則比較簡單:
?????1.線程自愿地放棄控制谬墙。線程顯示地放棄控制權(quán)、休眠或在I/O之前堵塞经备,都會出現(xiàn)這種情況拭抬。在這種情況下,檢查所有其他線程侵蒙,并且準(zhǔn)備運(yùn)行的線程中造虎,優(yōu)先級最高的那個線程會獲得CPU資源。
?????2.線程被優(yōu)先級更高的線程取代纷闺。對于這種情況算凿,沒有放棄控制權(quán)的低優(yōu)先級線程不管在做什么,都會被高優(yōu)先級線程簡單地取代犁功∶ズ洌基本上,只要高優(yōu)先級線程希望運(yùn)行浸卦,它就會取代低優(yōu)先級線程署鸡,這稱為搶占式多任務(wù)處理。
?????如果具有相同優(yōu)先級的兩個線程競爭CPU資源限嫌,這種情況有些復(fù)雜靴庆。對于windows操作系統(tǒng),優(yōu)先級相等的線程以循環(huán)方式自動獲得CPU資源怒医。對于其他操作系統(tǒng)炉抒,優(yōu)先級相等的線程必須資源的向其他線程放棄控制權(quán),否則其他線程就不能運(yùn)行稚叹。
注意:操作系統(tǒng)以不同的方式對具有相等優(yōu)先級的線程進(jìn)行上下文切換焰薄,可以會引起可移植性問題拿诸。
同步
?????因?yàn)槎嗑€程為程序引入了異步行為,所以必須提供一種在需要時強(qiáng)制同步的方法塞茅。例如亩码,如果希望兩個線程進(jìn)行通信并共享某個復(fù)雜的數(shù)據(jù)結(jié)構(gòu)。如鏈表凡桥,就需要以某種方式確保它們相互之間不會發(fā)生沖突蟀伸。也就是說蚀同,當(dāng)一個線程正在讀取該數(shù)據(jù)結(jié)構(gòu)時缅刽,必須阻止另外一個線程向該數(shù)據(jù)結(jié)構(gòu)寫入數(shù)據(jù)。
消息傳遞
?????將程序分隔到獨(dú)立的線程之后蠢络,需要定義它們之間相互通信的方式衰猛。當(dāng)使用某些其他語言編寫程序時,必須依賴操作系統(tǒng)建立 線程間相互通信的方式刹孔。java為兩個或多個線程之間的相互通信提供了一種簡潔的低成本方式啡省。java的消息傳遞系統(tǒng)允許某個線程進(jìn)入對象的同步方法,然后進(jìn)行等待髓霞,直到其他線程顯示的通知這個線程退出為止卦睹。
Thread類和Runnable接口
?????java的多線程系統(tǒng)是基于Thread類、Thread類的方法以及伴隨接口Runnable而構(gòu)建的方库。Thread類封裝了線程的執(zhí)行结序。因?yàn)椴荒苤苯右谜谶\(yùn)行的線程的細(xì)微狀態(tài),所以需要通過代理進(jìn)行處理纵潦,Thread實(shí)例就是線程的代理徐鹤。為了創(chuàng)建新的線程,程序可以擴(kuò)展Thread類或?qū)崿F(xiàn)Runnable接口邀层。