Java线程详解(7)-线程的调度
Java線程:線程的調(diào)度-休眠
? ? ? ? Java線程調(diào)度是Java多線程的核心,只有良好的調(diào)度,才能充分發(fā)揮系統(tǒng)的性能,提高程序的執(zhí)行效率。
????????這里要明確的一點(diǎn),不管程序員怎么編寫調(diào)度,只能最大限度的影響線程執(zhí)行的次序,而不能做到精準(zhǔn)控制。
????????線程休眠的目的是使線程讓出CPU的最簡(jiǎn)單的做法之一,線程休眠時(shí)候,會(huì)將CPU資源交給其他線程,以便能輪換執(zhí)行,當(dāng)休眠一定時(shí)間后,線程會(huì)蘇醒,進(jìn)入準(zhǔn)備狀態(tài)等待執(zhí)行。
????????線程休眠的方法是Thread.sleep(long millis)和Thread.sleep(long millis, int nanos),均為靜態(tài)方法,那調(diào)用sleep休眠的哪個(gè)線程呢?簡(jiǎn)單說,哪個(gè)線程調(diào)用sleep,就休眠哪個(gè)線程。
/**?*?Java線程:線程的調(diào)度-休眠?*/?? public?class?TestSleep?{??public?static?void?main(String[]?args)?{??Thread?t1=new?MyThread1();??Thread?t2=new?Thread(new?MyRunnable());??t1.start();??t2.start();??}?? }?? class?MyThread1?extends?Thread{??@Override??public?void?run()?{??for(int?i=0;i<3;i++){??System.out.println("線程1第"+i+"次執(zhí)行!");??try?{??Thread.sleep(50);??}?catch?(InterruptedException?e)?{??e.printStackTrace();??}??}??}???? }?? class?MyRunnable?implements?Runnable{??@Override??public?void?run()?{???????for(int?i=0;i<3;i++){??System.out.println("線程2第"+i+"次執(zhí)行!");??try?{??Thread.sleep(50);??}?catch?(InterruptedException?e)?{??e.printStackTrace();??}??}??}???? }??
????????執(zhí)行結(jié)果:
????????從上面的結(jié)果輸出可以看出,無法精準(zhǔn)保證線程執(zhí)行次序。
?
Java線程:線程的調(diào)度-優(yōu)先級(jí)
? ? ? ? 與線程休眠類似,線程的優(yōu)先級(jí)仍然無法保障線程的執(zhí)行次序。只不過,優(yōu)先級(jí)高的線程獲取CPU資源的概率較大,優(yōu)先級(jí)低的并非沒機(jī)會(huì)執(zhí)行。
????????線程的優(yōu)先級(jí)用1-10之間的整數(shù)表示,數(shù)值越大優(yōu)先級(jí)越高,默認(rèn)的優(yōu)先級(jí)為5。
????????在一個(gè)線程中開啟另外一個(gè)新線程,則新開線程稱為該線程的子線程,子線程初始優(yōu)先級(jí)與父線程相同。
/**?*?Java線程:線程的調(diào)度-優(yōu)先級(jí)?*/?? public?class?TestPriority?{??public?static?void?main(String[]?args)?{??Thread?t1=new?MyThread1();??Thread?t2=new?Thread(new?MyRunnable());??t1.setPriority(10);??t2.setPriority(1);??t1.start();??t2.start();??}?? }?? class?MyThread1?extends?Thread{??@Override??public?void?run()?{??for(int?i=0;i<10;i++){??System.out.println("線程1第"+i+"次執(zhí)行!");??try?{??Thread.sleep(100);??}?catch?(InterruptedException?e)?{??e.printStackTrace();??}??}??}???? }?? class?MyRunnable?implements?Runnable{??@Override??public?void?run()?{???????for(int?i=0;i<10;i++){??System.out.println("線程2第"+i+"次執(zhí)行!");??try?{??Thread.sleep(100);??}?catch?(InterruptedException?e)?{??e.printStackTrace();??}??}??}???? }??
????????執(zhí)行結(jié)果:
Java線程:線程的調(diào)度-讓步
? ? ? ? 線程的讓步含義就是使當(dāng)前運(yùn)行著線程讓出CPU資源,但是讓給誰(shuí)不知道,僅僅是讓出,線程狀態(tài)回到可運(yùn)行狀態(tài)。
????????線程的讓步使用Thread.yield()方法,yield()為靜態(tài)方法,功能是暫停當(dāng)前正在執(zhí)行的線程對(duì)象,并執(zhí)行其他線程。
/**?*?Java線程:線程的調(diào)度-讓步?*/?? public?class?Test?{??public?static?void?main(String[]?args)?{??Thread?t1=new?MyThread1();??Thread?t2=new?Thread(new?MyRunnable());??t1.start();??t2.start();??}?? }?? class?MyThread1?extends?Thread{??@Override??public?void?run()?{??for(int?i=0;i<10;i++){??System.out.println("線程1第"+i+"次執(zhí)行!");??????????}??}???? }?? class?MyRunnable?implements?Runnable{??@Override??public?void?run()?{???????for(int?i=0;i<10;i++){??System.out.println("線程2第"+i+"次執(zhí)行!");??Thread.yield();??}??}???? }??
????????執(zhí)行結(jié)果:
??
Java線程:線程的調(diào)度-合并
????????線程的合并的含義就是將幾個(gè)并行線程的線程合并為一個(gè)單線程執(zhí)行,應(yīng)用場(chǎng)景是當(dāng)一個(gè)線程必須等待另一個(gè)線程執(zhí)行完畢才能執(zhí)行時(shí)可以使用join方法。
????????join為非靜態(tài)方法,定義如下:
void?join()——等待該線程終止。????? void?join(longmillis)——等待該線程終止的時(shí)間最長(zhǎng)為?millis毫秒。????? void?join(longmillis,int?nanos)——等待該線程終止的時(shí)間最長(zhǎng)為?millis毫秒?+?nanos?納秒。???
/**?*?Java線程:線程的調(diào)度-合并?*/?? public?class?Test?{??public?static?void?main(String[]?args)?{??Thread?t1=new?MyThread1();???????t1.start();??for?(int?i?=?0;?i?<?20;?i++)?{??System.out.println("主線程第"?+?i?+"次執(zhí)行!");??if?(i>2)?{??try?{??///t1線程合并到主線程中,主線程停止執(zhí)行過程,轉(zhuǎn)而執(zhí)行t1線程,直到t1執(zhí)行完畢后繼續(xù)。??t1.join();??}?catch?(InterruptedException?e)?{??e.printStackTrace();??}??}??}??}?? }?? class?MyThread1?extends?Thread{??@Override??public?void?run()?{??for(int?i=0;i<10;i++){??System.out.println("線程1第"+i+"次執(zhí)行!");??????????}??}???? }??
????????執(zhí)行結(jié)果:
Java線程:線程的調(diào)度-守護(hù)線程
? ? ? ? 守護(hù)線程與普通線程寫法上基本么啥區(qū)別,調(diào)用線程對(duì)象的方法setDaemon(true),則可以將其設(shè)置為守護(hù)線程。
????????守護(hù)線程使用的情況較少,但并非無用,舉例來說,JVM的垃圾回收、內(nèi)存管理等線程都是守護(hù)線程。還有就是在做數(shù)據(jù)庫(kù)應(yīng)用時(shí)候,使用的數(shù)據(jù)庫(kù)連接池,連接池本身也包含著很多后臺(tái)線程,監(jiān)控連接個(gè)數(shù)、超時(shí)時(shí)間、狀態(tài)等等。
????????setDaemon方法的詳細(xì)說明:
public?final?void?setDaemon(boolean?on)將該線程標(biāo)記為守護(hù)線程或用戶線程。當(dāng)正在運(yùn)行的線程都是守護(hù)線程時(shí),Java虛擬機(jī)退出。??
????????該方法必須在啟動(dòng)線程前調(diào)用。
????????該方法首先調(diào)用該線程的 checkAccess方法,且不帶任何參數(shù)。這可能拋出 SecurityException(在當(dāng)前線程中)。
??????????參數(shù):on - 如果為true,則將該線程標(biāo)記為守護(hù)線程。
??????????拋出:
????????IllegalThreadStateException- 如果該線程處于活動(dòng)狀態(tài)。
????????SecurityException- 如果當(dāng)前線程無法修改該線程。
????????另請(qǐng)參見:
????????isDaemon(),checkAccess()
????????執(zhí)行結(jié)果:
????????從上面的執(zhí)行結(jié)果可以看出:
????????前臺(tái)線程是保證執(zhí)行完畢的,后臺(tái)線程還沒有執(zhí)行完畢就退出了。
????????實(shí)際上:JRE判斷程序是否執(zhí)行結(jié)束的標(biāo)準(zhǔn)是所有的前臺(tái)執(zhí)線程行完畢了,而不管后臺(tái)線程的狀態(tài),因此,在使用后臺(tái)縣城時(shí)候一定要注意這個(gè)問題。
?
總結(jié)
以上是生活随笔為你收集整理的Java线程详解(7)-线程的调度的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Java线程详解(6)-线程的交互
- 下一篇: Java线程详解(8)-线程的同步