怎樣處理InterruptedException,interruptedexception

來源:互聯網
上載者:User

怎樣處理InterruptedException,interruptedexception

Java 中的受檢查異常 InterruptedException 如何處理是令人頭痛的問題,下面是我對處理這個問題的理解。

Java 中的 InterruptedException 一直是一個令人頭疼的問題,對初級開發人員來說尤其如此。但實際上不應如此,這其實是一個很容易理解的問題。我會儘可能簡單地描述這個問題。

我們從這段代碼開始:

123 while (true) {  // Nothing}

它做了什嗎?什麼都沒做,只是無止境的消耗 CPU。我們能終止它嗎?在 Java 中是不行的。只有當你按下 Ctrl-C 來終止整個 JVM 時這段程式才會停止。在 Java 中沒有方式來終止一個線程,除非該線程自動結束。請務必牢記的這一原則,其它東西就顯而易見了。

我們將這個死迴圈放在一個線程裡:

1234567891011 Thread loop = new Thread(  new Runnable() {    @Override    public void run() {      while (true) {      }    }  });loop.start();// Now how do we stop it?

所以,怎樣才能停止一個需要停止的線程?

下面是 Java 中設計終止一個線程的方法。線上程的外部,設定一個標識變數(flag),然後線上程內部檢查改標識變數,從而實現線程的終止。過程如下:

123456789101112131415 Thread loop = new Thread(  new Runnable() {    @Override    public void run() {      while (true) {        if (Thread.interrupted()) {          break;        }        // Continue to do nothing      }    }  });loop.start();loop.interrupt();

這是終止線程的唯一方式,在這個例子裡使用了兩個方法。當調用 loop.interrupt() ,線程內部將標誌位設定為 true。當調用 interrupted() 時,立即返回,並將標識變數設定為 false。確實,這個方法就是這樣設計的。檢查標識變數、返回、設定為 false。我知道這很醜陋。

因此,我從來沒有線上程內調用 Thread.interrupted() 方法,因此標識變數為 true 時線程不會退出,沒有人能停止這個線程。準確地說,我會忽略他們對 interrupt() 方法的調用。雖然它們會要求終止線程,但是我會忽略它們。它們不能讓線程中斷。

因此,總結一下我們現在理解的內容,一種合理的設計是通過檢查標識變數來優雅地終止線程。如果代碼中不檢測標識變數,也不調用 Thread.interrupted(),那麼終止線程的方式就只能按下 Ctrl-C 了。

現在你聽明白這個邏輯了嗎?我希望是。

現在,JDK 中有一些方法來檢測標識變數,如果設定該標識變數,則會拋出 InterruptedException。例如,Thread.sleep() 方法的設計(一種最基本的方法):

123456789 public static void sleep(long millis)  throws InterruptedException {  while (/* You still need to wait */) {    if (Thread.interrupted()) {      throw new InterruptedException();    }    // Keep waiting  }}

為什麼要這麼做?為什麼不能等待並且不用去檢查標識變數?我相信一定有一個非常好的理由。理由如下(如果我說錯了,請修正我的錯誤):為了讓代碼變快或是中斷準備,沒有其他理由。

如果你的代碼足夠快,你從來不會檢測中斷標識變數,因為你不想處理任何中斷。如果你代碼很慢,可能需要執行數秒,這時你就有可能需要處理中斷了。

這就是為什麼 InterruptedException 是受檢查異常。這種設計告訴你,如果你想在幾毫秒內停止線程,確定你已經做好中斷準備。實踐中一般做如下處理:

12345 try {  Thread.sleep(100);} catch (InterruptedException ex) {  // Stop immediately and go home}

現在,你可以將它拋給負責捕獲該異常的上級程式去處理。這種觀點是有人在使用線程,並且會捕獲該異常。理想情況下,會終止線程,因為這就是標識變數的功能。如果拋出 InterruptedException,就意味著有人在檢查標識變數,線程需要儘可能快地終止。

線程的擁有者不想再等待線程執行,我們應該尊重擁有者的決定。

因此,當捕獲到 InterruptedException 時,你應該完成相關的操作再退出線程。

現在,我們再看一下 Thread.sleep() 的代碼:

12345678 public static void sleep(long millis)  throws InterruptedException {  while (/* ... */) {    if (Thread.interrupted()) {      throw new InterruptedException();    }  }}

請記住,Thread.interrupted() 不僅僅是返回標識變數的值,而且會將標識變數的值設定為 false。因此,一旦拋出 InterruptedException 異常,標誌變數將會重設。線程不再收到任何擁有者發送的插斷要求。

線程的所有者要求停止線程,Thread.sleep() 監測到該請求並將其刪除,再拋出 InterruptedException。如果你再次調用 Thread.sleep(),就不會響應任何插斷要求,也不會拋出任何異常。

知道我想要說的是什麼嗎?不要丟失 InterruptedException,這一點非常重要。我們不能吞噬該異常並繼續運行。這嚴重違背了 Java 多線程原則。所有者(線程的所有者)要求停止線程,而我們卻將其忽略,這是非常不好的想法。

下面是大多數人對 InterruptedException 的處理:

12345 try {  Thread.sleep(100);} catch (InterruptedException ex) {  throw new RuntimeException(ex);}

這看起來是符合邏輯的,但是這不能保證上層程式真正停止並退出。上層可能捕獲了運行時異常,所以這個線程還是存活的。線程所有者將會非常失望。

我們必須通知上層捕獲了一個插斷要求。我們不能只拋出運行時異常,這種行為太不負責了。當一個線程接收一個插斷要求時,我們不能只是將其轉換成為一個 RuntimeException。我們不能將這種嚴峻的情況如此輕鬆地對待。

這是我們應該做的:

123456 try {  Thread.sleep(100);} catch (InterruptedException ex) {  Thread.currentThread().interrupt(); // Here!  throw new RuntimeException(ex);}

我們需要將標識變數重新設定為 true。

現在,沒有人會譴責我們以不負責的態度來處理標識變數。我們發現其狀態為 true,將其清理,重新設定為 true,最後拋出運行時異常。接下來會發生什嗎?我們已經不關心了。

這就是我認為的處理方式。你可以找到這個問題更詳細的官方描述:Java 理論與實踐:InterruptedException 處理

原文連結: https://dzone.com/articles/how-to-handle-the-interruptedexception 翻譯:ImportNew.com - paddx
譯文連結: http://www.importnew.com/17027.html

 

全能程式員交流QQ群290551701,聚集很多互連網精英,技術總監,架構師,專案經理!開源技術研究,歡迎業內人士,大牛及新手有志於從事IT行業人員進入!

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.