日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問(wèn) 生活随笔!

生活随笔

當(dāng)前位置: 首頁(yè) > 编程资源 > 编程问答 >内容正文

编程问答

InterruptedException和中断线程的说明

發(fā)布時(shí)間:2023/12/3 编程问答 31 豆豆
生活随笔 收集整理的這篇文章主要介紹了 InterruptedException和中断线程的说明 小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

如果沒(méi)有將InterruptedException檢查為異常,則可能甚至沒(méi)人會(huì)注意到它-這實(shí)際上可以防止這些年來(lái)的幾個(gè)錯(cuò)誤。 但是由于必須對(duì)其進(jìn)行處理,因此許多人不正確或不加考慮地處理它。 讓我們以一個(gè)線程的簡(jiǎn)單示例為例,該線程定期進(jìn)行一些清理,但大多數(shù)情況下在兩次睡眠之間進(jìn)行。

class Cleaner implements Runnable {Cleaner() {final Thread cleanerThread = new Thread(this, "Cleaner");cleanerThread.start();}@Overridepublic void run() {while(true) {cleanUp();try {TimeUnit.SECONDS.sleep(1);} catch (InterruptedException e) {// TODO Auto-generated catch blocke.printStackTrace();}}}private void cleanUp() {//...}}

此代碼在很多層上都是錯(cuò)誤的!

  • 在某些環(huán)境中,在構(gòu)造函數(shù)中啟動(dòng)Thread可能不是一個(gè)好主意,例如,某些框架(如Spring)將創(chuàng)建動(dòng)態(tài)子類以支持方法攔截。 最后,我們將從兩個(gè)實(shí)例運(yùn)行兩個(gè)線程。
  • 吞下了InterruptedException ,并且異常本身未正確記錄
  • 此類為每個(gè)實(shí)例啟動(dòng)一個(gè)新線程,它應(yīng)改用ScheduledThreadPoolExecutor ,在許多實(shí)例之間共享(更健壯和更有效地使用內(nèi)存)
  • 同樣,使用ScheduledThreadPoolExecutor我們可以避免自己編寫(xiě)睡眠/工作循環(huán)代碼,并且還可以切換到固定速率,而不是此處介紹的固定延遲行為。
  • 最后但并非最不重要的一點(diǎn)是,即使Cleaner實(shí)例不再被其他任何東西引用,也沒(méi)有辦法擺脫該線程。
  • 所有問(wèn)題都是有效的,但是吞下InterruptedException是其最大的罪過(guò)。 在我們理解原因之前,讓我們先思考一下該異常的含義以及如何利用它來(lái)優(yōu)雅地中斷線程。 JDK中的許多阻止操作都聲明拋出InterruptedException ,包括:

    • Object.wait()
    • Thread.sleep()
    • Process.waitFor()
    • AsynchronousChannelGroup.awaitTermination()
    • java.util.concurrent.*各種阻塞方法,例如ExecutorService.awaitTermination() , Future.get() , BlockingQueue.take() , Semaphore.acquire() Condition.await()以及許多其他方法
    • SwingUtilities.invokeAndWait()

    請(qǐng)注意,阻塞I / O不會(huì)引發(fā)InterruptedException (這很可惜)。 如果所有這些類都聲明了InterruptedException ,那么您可能想知道何時(shí)會(huì)拋出此異常?

    • 當(dāng)某個(gè)線程在聲明InterruptedException某些方法上被阻塞并且您在該線程上調(diào)用Thread.interrupt()時(shí),很可能阻塞的方法將立即引發(fā)InterruptedException 。
    • 如果將任務(wù)提交到線程池( ExecutorService.submit() ),并且在執(zhí)行任務(wù)時(shí)調(diào)用Future.cancel(true) 。 在這種情況下,線程池將嘗試為您中斷正在運(yùn)行該任務(wù)的線程,從而有效地中斷您的任務(wù)。

    知道InterruptedException實(shí)際含義后,我們就能夠正確地處理它。 如果有人試圖中斷我們的線程,而我們通過(guò)捕獲InterruptedException發(fā)現(xiàn)了它,則最合理的做法是讓該線程完成,例如:

    class Cleaner implements Runnable, AutoCloseable {private final Thread cleanerThread;Cleaner() {cleanerThread = new Thread(this, "Cleaner");cleanerThread.start();}@Overridepublic void run() {try {while (true) {cleanUp();TimeUnit.SECONDS.sleep(1);}} catch (InterruptedException ignored) {log.debug("Interrupted, closing");}}//... @Overridepublic void close() {cleanerThread.interrupt();} }

    注意, try-catch塊現(xiàn)在圍繞while循環(huán)。 這樣,如果sleep()拋出InterruptedException ,我們將跳出循環(huán)。 您可能會(huì)爭(zhēng)辯說(shuō),我們應(yīng)該記錄InterruptedException的堆棧跟蹤。 這取決于情況,因?yàn)樵谶@種情況下中斷線程是我們真正期望的,而不是失敗。 但這取決于你。 最重要的是,如果sleep()被另一個(gè)線程中斷,我們將很快完全脫離run() 。 如果您非常小心,您可能會(huì)問(wèn),如果線程在cleanUp()方法中而不是在睡眠時(shí)中斷線程,會(huì)發(fā)生什么情況? 通常,您會(huì)遇到這樣的手動(dòng)標(biāo)記:

    private volatile boolean stop = false;@Override public void run() {while (!stop) {cleanUp();TimeUnit.SECONDS.sleep(1);} }@Override public void close() {stop = true; }

    但是請(qǐng)注意, stop標(biāo)志(必須是volatile !)不會(huì)中斷阻塞操作,我們必須等到sleep()完成。 另一方面,有人可能會(huì)爭(zhēng)辯說(shuō),顯式flag可以更好地控制我們,因?yàn)槲覀兛梢噪S時(shí)監(jiān)視其值。 事實(shí)證明,線程中斷的工作方式相同。 如果有人在執(zhí)行非阻塞計(jì)算時(shí)中斷了線程(例如在cleanUp()內(nèi)部),則不會(huì)立即中斷此類計(jì)算。 但是,線程被標(biāo)記為已中斷,并且隨后的所有阻塞操作(例如sleep() )都將立即立即拋出InterruptedException因此我們不會(huì)丟失該信號(hào)。

    如果我們編寫(xiě)仍想利用線程中斷功能的非阻塞線程,我們也可以利用這一事實(shí)。 不必依賴于InterruptedException我們只需定期檢查T(mén)hread.isInterrupted() :

    public void run() {while (Thread.currentThread().isInterrupted()) {someHeavyComputations();} }

    在上方,如果有人中斷了我們的線程,則在someHeavyComputations()返回時(shí)我們將立即放棄計(jì)算。 如果它運(yùn)行了兩個(gè)長(zhǎng)時(shí)間或無(wú)限期,我們將永遠(yuǎn)不會(huì)發(fā)現(xiàn)中斷標(biāo)志。 有趣的是, interrupted標(biāo)志不是一次性的 。 我們可以調(diào)用Thread.interrupted()而不是isInterrupted() ,這將重置interrupted標(biāo)志并且我們可以繼續(xù)。 有時(shí)您可能想忽略中斷標(biāo)志并繼續(xù)運(yùn)行。 在這種情況下, interrupted()可能會(huì)派上用場(chǎng)。 順便說(shuō)一句,我(不精確地)將“吸氣劑”稱為“ Heisengetters ”,它改變了被觀察物體的狀態(tài) 。

    注意

    如果您是老派程序員,您可能會(huì)想起Thread.stop()方法,該方法已被棄用10年了 。 在Java 8中,有計(jì)劃“取消實(shí)現(xiàn)它” ,但在1.8u5中它仍然存在。 但是,不要使用它,而是使用Thread.stop()將任何代碼重構(gòu)為T(mén)hread.interrupt() 。

    番石榴的

    您很少會(huì)完全忽略InterruptedException 。 在這種情況下,請(qǐng)查看番石榴的《 Uninterruptibles 。 它具有許多實(shí)用方法,如sleepUninterruptibly()或awaitUninterruptibly(CountDownLatch) 。 只是要小心他們。 我知道他們沒(méi)有聲明InterruptedException (可能很少),但是它們也完全防止了當(dāng)前線程的中斷–這是非常不尋常的。

    摘要

    到現(xiàn)在為止,我希望您對(duì)為什么某些方法引發(fā)InterruptedException有所了解。 主要的收獲是:

    • 捕獲的InterruptedException應(yīng)該得到正確處理-大多數(shù)情況下,這意味著完全脫離當(dāng)前任務(wù)/循環(huán)/線程
    • 吞下InterruptedException很少是一個(gè)好主意
    • 如果線程不在阻塞調(diào)用中而被中斷,請(qǐng)使用isInterrupted() 。 當(dāng)線程已經(jīng)被中斷時(shí)也進(jìn)入阻塞方法應(yīng)該立即拋出InterruptedException 。

    翻譯自: https://www.javacodegeeks.com/2014/06/interruptedexception-and-interrupting-threads-explained.html

    總結(jié)

    以上是生活随笔為你收集整理的InterruptedException和中断线程的说明的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。

    如果覺(jué)得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。