大战熟女丰满人妻av-荡女精品导航-岛国aaaa级午夜福利片-岛国av动作片在线观看-岛国av无码免费无禁网站-岛国大片激情做爰视频

專注Java教育14年 全國咨詢/投訴熱線:400-8080-105
動(dòng)力節(jié)點(diǎn)LOGO圖
始于2009,口口相傳的Java黃埔軍校
首頁 學(xué)習(xí)攻略 Java學(xué)習(xí) Java高級(jí)編程實(shí)用教程,如何使用線程的休眠

Java高級(jí)編程實(shí)用教程,如何使用線程的休眠

更新時(shí)間:2019-08-12 10:42:43 來源:動(dòng)力節(jié)點(diǎn) 瀏覽2872次

  線程休眠和中斷


  我們知道了在編程過程中創(chuàng)建線程,并啟動(dòng)以后,線程會(huì)交由操作系統(tǒng)來管理調(diào)度執(zhí)行一個(gè)我們指定的計(jì)算任務(wù)。


  如果沒有其它異常情況出現(xiàn)的話,它會(huì)持續(xù)運(yùn)行直到我們實(shí)現(xiàn)的run()方法執(zhí)行完畢為止。


  那么我們通常在什么情況下需要?jiǎng)?chuàng)建單獨(dú)的線程呢?一般是在我們的程序需要執(zhí)行一個(gè)比較耗時(shí)的任務(wù),或者需要一個(gè)程序不斷的重復(fù)執(zhí)行某種動(dòng)作,這些基本上都屬于我們程序的后臺(tái)來負(fù)責(zé)處理的問題,比如檢查某種狀態(tài)或者動(dòng)作,而不影響其它任務(wù)的執(zhí)行時(shí),需要?jiǎng)?chuàng)建單獨(dú)的線程來操作。


  耗時(shí)較長的工作比如需要掃描某個(gè)特定的目錄結(jié)構(gòu)中所有文件,到數(shù)據(jù)庫中查詢一個(gè)大容量的數(shù)據(jù)表等。


  需要持續(xù)的周期性間隔的查看某個(gè)狀態(tài)和結(jié)果的任務(wù),雖然我們可以直接在借助while循環(huán)來執(zhí)行,但是如此會(huì)浪費(fèi)太多的CPU時(shí)間,因?yàn)槲覀兊腃PU會(huì)一次又一次的被切換占用來執(zhí)行它。這時(shí)我們需要讓監(jiān)控循環(huán)能夠等待一定時(shí)間間隔再檢查,從而減少CPU無效時(shí)間的占用。


  對(duì)于此類用例,更好的方法是讓執(zhí)行監(jiān)控任務(wù)的線程能夠暫停執(zhí)行特定間隔,再次期間CPU可以去處理其它計(jì)算任務(wù)。


  這種情況我們可以調(diào)用類java.lang.Thread的sleep()方法來實(shí)現(xiàn),如下例所示:


image.png

  調(diào)用sleep()使當(dāng)前線程進(jìn)入睡眠狀態(tài),而不消耗任何處理時(shí)間。


  該方法被調(diào)用意味著當(dāng)前線程從活動(dòng)線程列表中刪除自己,調(diào)度程序在下一次執(zhí)行時(shí)不會(huì)調(diào)度它直到指定的毫秒數(shù)過后才會(huì)再次調(diào)度它執(zhí)行。


  這里需要注意的是我們傳遞給sleep()方法的時(shí)間只能是作為調(diào)度程序的一個(gè)指示,實(shí)際的執(zhí)行不一定會(huì)絕對(duì)準(zhǔn)確的按照指定的時(shí)間進(jìn)行。


  主要是因?yàn)椴僮飨到y(tǒng)在執(zhí)行調(diào)度時(shí),實(shí)際執(zhí)行時(shí)可能會(huì)出現(xiàn)線程提前或延遲幾納秒或幾毫秒返回的情況。


  因此,我們不建議將sleep()方法用于對(duì)時(shí)間精度有比較高要求的實(shí)時(shí)調(diào)度上。但是對(duì)于大多數(shù)情況來說,在這種納秒或毫秒級(jí)別達(dá)到的精度已經(jīng)足夠了。


  線程的中斷現(xiàn)象


  因?yàn)橹袛嗍遣僮飨到y(tǒng)調(diào)度CPU任務(wù)執(zhí)行的一個(gè)重要機(jī)制,是線程交互的一個(gè)非常基本的特性,可以理解為一個(gè)線程向另一個(gè)線程發(fā)送的簡單中斷消息。


  我們知道中斷機(jī)制是通過中斷異常來提供處理入口的。


  所以,當(dāng)我們在一個(gè)線程上調(diào)用sleep()方法使其處于睡眠狀態(tài)時(shí),它可能會(huì)被中斷,表現(xiàn)為拋出InterruptedException異常。


  在上面的代碼示例中,您可能已經(jīng)注意到sleep()可能拋出InterruptedException。


  而關(guān)聯(lián)線程可以通過調(diào)用Thread.interrupted()方法來檢查自己是否被中斷了。


  或者當(dāng)它將時(shí)間花費(fèi)在sleep()這樣的方法中時(shí)就是隱式的中斷,也會(huì)在中斷時(shí)拋出異常。


  讓我們用下面的代碼例子來仔細(xì)看看中斷:

QQ截圖20190812103901.png

  簡單分析一下上面的示例代碼,我們在main方法中,首先啟動(dòng)一個(gè)新線程myThread,如果不中斷它,它將休眠很長時(shí)間(大約290年)。


  這當(dāng)然不能這樣下去,所以為了能提前完成程序執(zhí)行,myThread線程通過在main方法中調(diào)用它的實(shí)例方法interrupt()來執(zhí)行中斷。


  由于myThread線程從開始執(zhí)行就處在sleep()調(diào)用中,調(diào)用interrupt()方法結(jié)果導(dǎo)致InterruptedException異常發(fā)生,被catch捕獲,從而在控制臺(tái)上打印為“myThread線程被異常中斷!”


  然后繼續(xù)執(zhí)行while循環(huán)檢查該線程是否被中斷,如果沒有就執(zhí)行空循環(huán),如果被中斷就繼續(xù)執(zhí)行完該線程任務(wù),即執(zhí)行打印“myThread線程被第二次中斷”。


  我們在主線程中多次執(zhí)行sleep()方法是給予子線程執(zhí)行機(jī)會(huì)。


  在記錄了異常之后,線程會(huì)忙著等待,直到設(shè)置了線程上的中斷標(biāo)志。


  這也是通過調(diào)用線程實(shí)例變量上的interrupt()從主線程設(shè)置的。


  總的來說,我們看到控制臺(tái)的輸出如下:

image.png

  從輸出中可以看到,調(diào)度程序在再次啟動(dòng)myThread之前已經(jīng)執(zhí)行了主線程。


  因此,myThread在主線程開始休眠后打印出異常的接收。


  其實(shí),在使用多個(gè)線程編程時(shí),通常我們會(huì)發(fā)現(xiàn)線程的日志輸出在某種程度上難以預(yù)測,因?yàn)楹茈y計(jì)算接下來執(zhí)行哪個(gè)線程。


  當(dāng)我們必須處理更多的線程時(shí),我們就會(huì)發(fā)現(xiàn)而這些線程的暫停并沒有像上面的示例中那樣符合預(yù)期,常常情況會(huì)變得很糟。


  在這些情況下,整個(gè)程序得到某種內(nèi)部動(dòng)態(tài),這使得并發(fā)編程成為一項(xiàng)具有挑戰(zhàn)性的任務(wù)。


  join線程


  前面我們看到的,在線程執(zhí)行過程中,我們可以讓線程休眠,直到它被另一個(gè)線程喚醒。這能夠充分的利用CPU的處理時(shí)間。


  由于在大量線程同時(shí)執(zhí)行時(shí),線程的暫停已經(jīng)無法準(zhǔn)確的調(diào)度線程執(zhí)行,所以迫切需要線程的另一個(gè)重要特性就是線程能夠等待另一個(gè)線程的終止。


  也就是說將線程按照某種先后順序排列起來中。


  這里假設(shè)我們必須實(shí)現(xiàn)某種數(shù)字處理操作,該操作可以劃分為多個(gè)并行運(yùn)行的線程。


  啟動(dòng)所謂工作線程的主線程必須等待,直到所有子線程都終止。


  在我們的主方法中,我們創(chuàng)建了一個(gè)由5個(gè)線程組成的數(shù)組,這些線程都是一個(gè)接一個(gè)地啟動(dòng)的。

image.png

  我們先看一下在不使用join()方法的執(zhí)行情況:

image.png

  我們可以看到,主線程率先執(zhí)行完成,然后才是各個(gè)子線程依次完成。


  而當(dāng)我們增加Join調(diào)用時(shí):

image.png

  一旦啟動(dòng)它們,我們就在主線程中等待它們的終止。線程本身通過計(jì)算一個(gè)接一個(gè)的隨機(jī)數(shù)來模擬一些數(shù)字處理。


  一旦完成,就打印出“線程結(jié)束!”。最后主線程承認(rèn)所有子線程的終止:

image.png

  我們將觀察到,“完成”消息的順序因執(zhí)行而異。如果多次執(zhí)行該程序,我們可能會(huì)發(fā)現(xiàn)最先完成的線程并不總是相同的。但是,最后一條語句始終是等待它的子線程的主線程。


  觀察上面兩次執(zhí)行結(jié)果,我們發(fā)現(xiàn)join()的作用就是讓主線程等待子線程的執(zhí)行,而不是采用使主線程休眠的方式。


  這種處理主要用在在某些情況下,我們將不得不等待線程的結(jié)束。例如,我們可能有一個(gè)程序,它將開始初始化它需要的資源,然后再執(zhí)行其余的執(zhí)行。我們可以用多個(gè)獨(dú)立線程的形式運(yùn)行初始化任務(wù),并等待這些初始化線程執(zhí)行完成后再開始繼續(xù)執(zhí)行程序的其余部分。


  為此,我們可以使用Thread類的join()方法。當(dāng)我們使用Thread對(duì)象調(diào)用此方法時(shí),它將暫停調(diào)用線程的執(zhí)行,直到被調(diào)用的對(duì)象完成執(zhí)行。


  總結(jié)


  對(duì)于線程的調(diào)度管理,始終是并發(fā)編程中最重要的課題,通過上面的說明我們一定要記住,sleep()雖然能夠讓線程休眠,但是我們提供的休眠時(shí)間參數(shù)只是個(gè)參考值,并不能精確的被采用,而join()方法,主要用于讓父線程等待子線程結(jié)束之后才能繼續(xù)運(yùn)行。


提交申請后,顧問老師會(huì)電話與您溝通安排學(xué)習(xí)

免費(fèi)課程推薦 >>
技術(shù)文檔推薦 >>
主站蜘蛛池模板: 夜夜操操操 | 亚欧aⅴ天堂在线 | 国产精品久久久久无码av | 亚洲啪啪看看 | 国产99在线 | 日韩不卡视频在线观看 | jiucao在线观看精品 | 四虎 在线播放 | 高清欧美色欧美综合网站 | 亚洲国产日韩综合久久精品 | 亚洲国产成人久久99精品 | 激情综合婷婷亚洲图片 | 不卡国产视频 | 97福利影院 | 9热这里只有真品 | 天天干天天色天天 | 欧美性色欧美a在线观看 | 欧美日韩在线视频播放 | 97色在线视频 | 一级美国乱色毛片 | 九九九久久久久久久爱 | 在线播放亚洲 | 欧美日韩中文字幕在线手机版本 | 午夜看一级特黄a大片 | 在线观看高清国产福利视频 | 看免费黄色一级视频 | 色丁香综合| 国产福利不卡视频在免费播放 | 手机观看毛片 | 正在播放一区 | 伊人99在线观看 | a亚洲欧美中文日韩在线v日本 | 亚洲视频在线免费播放 | 国产欧美大片 | 欧美日韩不卡中文字幕在线 | 国产精品高清全国免费观看 | 日本精品视频网站 | 日本不卡免费一区 | 欧美不卡在线视频 | 久夜tv | 四虎在线观看免费视频 |