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

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

InterruptedException和中断线程的解释

發布時間:2023/12/3 编程问答 29 豆豆
生活随笔 收集整理的這篇文章主要介紹了 InterruptedException和中断线程的解释 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

如果沒有將InterruptedException檢查為異常,則可能甚至沒人會注意到它–實際上,這些年來可以防止出現幾個錯誤。 但是由于必須對其進行處理,因此許多人不正確或不加考慮地處理它。 讓我們以一個線程的簡單示例為例,該線程定期進行一些清理,但大多數情況下在兩次睡眠之間進行。

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() {//...}}

此代碼在很多層上都是錯誤的!

  • 在某些環境中,在構造函數中啟動Thread可能不是一個好主意,例如,某些框架(如Spring)將創建動態子類來支持方法攔截。 最后,我們將從兩個實例運行兩個線程。
  • 吞下了InterruptedException ,并且異常本身未正確記錄
  • 此類為每個實例啟動一個新線程,它應改用ScheduledThreadPoolExecutor ,在許多實例之間共享(更健壯和更有效地使用內存)
  • 同樣,使用ScheduledThreadPoolExecutor我們可以避免自己編寫睡眠/工作循環代碼,并且還可以切換到固定速率,而不是此處介紹的固定延遲行為。
  • 最后但并非最不重要的一點是,即使Cleaner實例不再被其他任何東西引用,也沒有辦法擺脫此線程。
  • 所有問題都是有效的,但是吞沒InterruptedException是其最大的罪過。 在我們理解原因之前,讓我們先思考一下該異常的含義以及如何利用它來優雅地中斷線程。 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()

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

    • 當某個線程在聲明InterruptedException某個方法上被阻塞并且您在該線程上調用Thread.interrupt()時,很可能阻塞的方法將立即拋出InterruptedException 。
    • 如果您將任務提交到線程池( ExecutorService.submit() ),并且在執行任務時調用Future.cancel(true) 。 在這種情況下,線程池將嘗試為您中斷正在運行此類任務的線程,從而有效地中斷了您的任務。

    知道InterruptedException實際含義后,我們就可以正確處理它。 如果有人試圖中斷我們的線程,而我們通過捕獲InterruptedException發現了它,則最合理的做法是讓該線程完成,例如:

    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塊現在圍繞while循環。 這樣,如果sleep()拋出InterruptedException ,我們將跳出循環。 您可能會爭辯說,我們應該記錄InterruptedException的堆棧跟蹤。 這取決于情況,因為在這種情況下中斷線程是我們真正希望的,而不是失敗。 但這取決于你。 最重要的是,如果sleep()被另一個線程中斷,我們將很快完全脫離run() 。 如果您非常小心,您可能會問,如果線程在cleanUp()方法中而不是在睡眠時中斷線程,會發生什么情況? 通常,您會遇到這樣的手動標記:

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

    但是請注意, stop標志(必須是volatile !)不會中斷阻塞操作,我們必須等到sleep()完成。 另一方面,有人可能會爭辯說,顯式flag可以更好地控制我們,因為我們可以隨時監視其值。 事實證明,線程中斷的工作方式相同。 如果有人在執行非阻塞計算時中斷了線程(例如在cleanUp()內部),則此類計算不會立即中斷。 但是,線程被標記為已中斷,并且隨后的所有阻塞操作(例如sleep() )都將立即立即拋出InterruptedException因此我們不會丟失該信號。

    如果我們編寫仍想利用線程中斷功能的非阻塞線程,那么我們也可以利用這一事實。 不必依賴于InterruptedException我們只需定期檢查Thread.isInterrupted() :

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

    在上方,如果有人中斷了我們的線程,則在someHeavyComputations()返回時我們將立即放棄計算。 如果它運行了兩個長時間或無限期,我們將永遠不會發現中斷標志。 有趣的是, interrupted標志不是一次性的 。 我們可以調用Thread.interrupted()而不是isInterrupted() ,這將重置interrupted標志并且我們可以繼續。 有時您可能想忽略中斷標志并繼續運行。 在這種情況下, interrupted()可能會派上用場。 順便說一句,我(不精確地)稱“吸氣劑”來改變被觀察物體的狀態 “ 海森格 ”。

    注意

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

    番石榴的

    很少您可能會完全忽略InterruptedException 。 在這種情況下,請查看Guava的Uninterruptibles 。 它具有許多實用方法,例如sleepUninterruptibly()或awaitUninterruptibly(CountDownLatch) 。 只是要小心他們。 我知道他們沒有聲明InterruptedException (可能很少),但是它們也完全防止了當前線程被中斷–這是非常不尋常的。

    摘要

    到現在為止,我希望您對為什么某些方法引發InterruptedException有所了解。 主要的收獲是:

    • 捕獲的InterruptedException應該得到正確處理-大多數情況下,這意味著完全脫離當前任務/循環/線程
    • 吞下InterruptedException很少是一個好主意
    • 如果線程不在阻塞調用中時被中斷,請使用isInterrupted() 。 當線程已經被中斷時也進入阻塞方法應該立即拋出InterruptedException 。

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

    總結

    以上是生活随笔為你收集整理的InterruptedException和中断线程的解释的全部內容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。