java 手动线程调度_Java Thread 多线程 操作线程
5、線程的創(chuàng)建和啟動
A、繼承Thread類或?qū)崿F(xiàn)Runnable接口,重寫或?qū)崿F(xiàn)run方法,run方法代表線程要完成的任務
B、創(chuàng)建Thread子類或是Runnable的實現(xiàn)類,即創(chuàng)建的線程對象;不同的是接口實現(xiàn)線程,
需要將接口的實現(xiàn)類作為參數(shù)傳遞給Thread類的構(gòu)造參數(shù)
C、用線程對象的start方法啟動線程
6、繼承Thread和實現(xiàn)Runnable接口創(chuàng)建線程的區(qū)別
采用Runnable接口實現(xiàn)線程:
優(yōu)勢:
A、線程類只是實現(xiàn)了Runnable接口,還可以繼承其他的類
B、在這種方式下,可以多個線程共享同一個目標對象,所以很合適多個線程來處理同一份資源的情況,
從而可以將CPU、代碼和數(shù)據(jù)分開,形成清晰的模型,較好的面相對象思想。
劣勢:編程稍微復雜,如果需要訪問當前線程需要用Thread.currentThread方法來獲取
采用繼承Thread類的方式實現(xiàn)線程:
優(yōu)勢:編寫簡單,如果要獲得當前線程直接this即可
劣勢:線程類繼承了Thread,不能在繼承其他類
相對而言,用Runnable的方式更好,具體可以根據(jù)當前需要而定;
7、線程生命周期
線程被創(chuàng)建啟動后,不并不是啟動后就進入了執(zhí)行狀態(tài),也不是一直處于的執(zhí)行狀態(tài)。
線程的生命周期分為創(chuàng)建(new)、就緒(Runnable)、運行(running)、阻塞(Blocked)、死亡(Dead)五種狀態(tài)。
線程啟動后不會一直霸占CPU資源,所以CPU需要在多條線程中切換執(zhí)行,線程就會在多次的運行和阻塞中切換。
8、新建(new)和就緒(Runnable)狀態(tài)
當new一個線程后,該線程處于新建狀態(tài),此時它和Java對象一樣,僅僅由Java虛擬機為其分配內(nèi)存空間,并初始化成員變量。
此時線程對象沒有表現(xiàn)出任何的動態(tài)特征,程序也不會執(zhí)行線程的執(zhí)行體。
注意:run方法是線程的執(zhí)行體,不能由我們手動調(diào)用。我們可以用start方法啟動線程,系統(tǒng)會把run方法當成線程的執(zhí)行體來運行,
如果直接調(diào)用線程對象run方法,則run方法立即會被運行。而且在run方法返回之前其他線程無法并行執(zhí)行,
也就是說系統(tǒng)會把當前線程類當成一個普通的Java對象,而run方法也是一個普通的方法,而不是線程的執(zhí)行體。
9、運行(running)和阻塞(Blocked)狀態(tài)
如果處于就緒狀態(tài)的線程就獲得了CPU,開始執(zhí)行run方法的線程執(zhí)行體,則該線程處于運行狀態(tài)。
單CPU的機器,任何時刻只有一條線程處于運行狀態(tài)。當然,在多CPU機器上將會有多線程并行(parallel)執(zhí)行,
當線程大于CPU數(shù)量時,依然會在同一個CPU上切換執(zhí)行。
線程運行機制:一個線程運行后,它不可能一直處于運行狀態(tài)(除非它執(zhí)行的時間很短,瞬間執(zhí)行完成),線程在運行過程中需要中斷,
目的是讓其他的線程有運行機會,線程的調(diào)度取決于底層的策略。對應搶占式的系統(tǒng)而言,系統(tǒng)會給每個可執(zhí)行的線程一個小時間段來處理任務,
當時間段到達系統(tǒng)就會剝奪該線程的資源,讓其他的線程有運行的機會。在選擇下一個線程時,系統(tǒng)會考慮線程優(yōu)先級。
以下情況會出現(xiàn)線程阻塞狀態(tài):
A、線程調(diào)用sleep方法,主動放棄占用的處理器資源
B、線程調(diào)用了阻塞式IO方法,在該方法返回前,該線程被阻塞
C、線程試圖獲得一個同步監(jiān)視器,但該同步監(jiān)視器正被其他線程所持有。
D、線程等待某個通知(notify)
E、程序調(diào)用了suspend方法將該線程掛起。不過這個方法容易導致死鎖,盡量不免使用該方法
當線程被阻塞后,其他線程將有機會執(zhí)行。被阻塞的線程會在合適的時候重新進入就緒狀態(tài),注意是就緒狀態(tài)不是運行狀態(tài)。
也就是被阻塞線程在阻塞解除后,必須重新等待線程調(diào)度器再次調(diào)用它。
針對上面線程阻塞的情況,發(fā)生以下特定的情況可以解除阻塞,讓進程進入就緒狀態(tài):
A、調(diào)用sleep方法的經(jīng)過了指定的休眠時間
B、線程調(diào)用的阻塞IO已經(jīng)返回,阻塞方法執(zhí)行完畢
C、線程成功獲得了試圖同步的監(jiān)視器
D、線程正在等待某個通知,其他線程發(fā)出了通知
E、處于掛起狀態(tài)的線程調(diào)用了resume恢復方法
線程從阻塞狀態(tài)只能進入就緒狀態(tài),無法進入運行狀態(tài)。而就緒和運行狀態(tài)之間的轉(zhuǎn)換通常不受程序控制,而是由系統(tǒng)調(diào)度所致的。
當就緒狀態(tài)的線程獲得資源時,該線程進入運行狀態(tài);當運行狀態(tài)的線程事情處理器資源時就進入了就緒狀態(tài)。
但對調(diào)用了yield的方法就例外,此方法可以讓運行狀態(tài)轉(zhuǎn)入就緒狀態(tài)。
10、線程死亡(Dead)狀態(tài)
線程會在以下方式進入死亡狀態(tài):
A、run方法執(zhí)行完成,線程正常結(jié)束
B、線程拋出未捕獲的異常或Error
C、直接調(diào)用該線程的stop方法來結(jié)束線程—該方法易導致死鎖,注意使用
注意:當主線程結(jié)束的時候,其他線程不受任何影響。一旦子線程啟動后,會擁有和主線程相同的地位,不受主線程影響。
isAlive方法可以測試當前線程是否死亡,當線程處于就緒、運行、阻塞狀態(tài),該方法返回true,如果線程處于新建或死亡狀態(tài)就會返回false。
不要試圖對死亡的線程調(diào)用start方法,來啟動它。死亡線程不可能再次運行。
11、控制線程
Java線程提供了很多工具方法,這些方法都很好的控制線程
A、join線程
讓一個線程等待另一個線程完成的方法。當某個程序執(zhí)行流中調(diào)用其他線程的join方法時,調(diào)用線程將會被阻塞,直到被join方法的join線程執(zhí)行完成為止。
join方法通常有使用線程的程序調(diào)用,將大問題劃分成許多小問題。每個小問題分配一個線程。當所有的小問題得到處理后,再調(diào)用主線程進一步操作。
join有三種重載模式:
一、join等待被join的線程執(zhí)行完成
二、join(long millis)等待被join的線程時間最長為millis毫秒,如果在millis毫秒外,被join的線程還沒有執(zhí)行完則不再等待
三、join(long millis, int nanos)被join的線程等待時間長為millis毫秒加上nanos微秒
通常我們很少用第三種join,原因有二:程序?qū)r間的精度無需精確到千分之一毫秒
計算機硬件、操作系統(tǒng)也無法做到精確到千分之一毫秒
B、后臺線程
有一種線程,在后臺運行,它的任務是為其他線程提供服務,這種線程被稱為“后臺線程(Daemon Thread)”,有被稱為“守護線程”或“精靈線程”。
JVM的垃圾回收器線程就是后臺進程。
后臺進程有個特征是:如果前臺的進程都死亡,那么后臺進程也死亡。(它為前臺進程服務)
用Thread的setDaemon (true)方法可以指定當前線程為后臺線程。
注意:前臺線程執(zhí)行完成死亡后,JVM會通知后臺線程,后臺線程就會死亡。但它得到通知到后臺線程作成響應,需要一段時間,
而且要將某個線程設置為后臺線程,必需要在該線程啟動前設置,也就是說設置setDaemon必需在start方法前面調(diào)用。
否則會出現(xiàn)java.lang.IllegalThreadStateException異常
C、線程休眠sleep
如果需要當前線程暫停一段時間,并進入阻塞狀態(tài)就需要用sleep,sleep有2中重載方式:
sleep(long millis)讓當前線程暫停millis毫秒后,并進入阻塞狀態(tài),該方法受系統(tǒng)計時器和線程調(diào)度器的影響
sleep(long millis, int nanos)讓當前正在執(zhí)行的線程暫停millis毫秒+nanos微秒,并進入阻塞
當調(diào)用sleep方法進入阻塞狀態(tài)后,在sleep時間段內(nèi),該線程不會獲得執(zhí)行機會,即使沒有其他可運行的線程,處于sleep的線程不會執(zhí)行。
D、線程讓步y(tǒng)ield
yield和sleep有點類似,它也可以讓當前執(zhí)行的線程暫停,但它不會阻塞線程,只是將該線程轉(zhuǎn)入到就緒狀態(tài)。
yield只是讓當前線程暫停下,讓系統(tǒng)線程調(diào)度器重新調(diào)度下。
當yield的線程后,當前線程暫停。系統(tǒng)線程調(diào)度器會讓優(yōu)先級相同或是更高的線程運行。
sleep和yield的區(qū)別
(1)、sleep方法暫停當前線程后,會給其他線程執(zhí)行集合,不會理會線程的優(yōu)先級。但yield則會給優(yōu)先級相同或高優(yōu)先級的線程執(zhí)行機會
(2)、sleep方法會將線程轉(zhuǎn)入阻塞狀態(tài),直到經(jīng)過阻塞時間才會轉(zhuǎn)入到就緒狀態(tài);而yield則不會將線程轉(zhuǎn)入到阻塞狀態(tài),它只是強制當前線程進入就緒狀態(tài)。
因此完全有可能調(diào)用yield方法暫停之后,立即再次獲得處理器資源繼續(xù)運行。
(3)、sleep聲明拋出了InterruptedException異常,所以調(diào)用sleep方法時,要么捕獲異常,要么拋出異常。而yield沒有申明拋出任何異常
E、改變線程優(yōu)先級
每個線程都有優(yōu)先級,優(yōu)先級決定線程的運行機會的多少。
每個線程默認和它創(chuàng)建的父類的優(yōu)先級相同,main方法的優(yōu)先級是普通優(yōu)先級,那在main方法中創(chuàng)建的子線程都是普通優(yōu)先級。
getPriority(int newPriority)/setPriority(int)
設置優(yōu)先級有以下級別:
MAX_PRIORITY 值是10
MIN_PRIORITY 值是1
NORM_PRIORITY 值是5
范圍是1-10;
總結(jié)
以上是生活随笔為你收集整理的java 手动线程调度_Java Thread 多线程 操作线程的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
 
                            
                        - 上一篇: java 反射 ppt_Java反射的基
- 下一篇: python替换文本文件单词_在大型文本
