2017-04-20 51 views
1

我想知道在主線程中處理InterruptedException的正確方法是什麼。主線程中斷了嗎?在主線程中處理InterruptedException

我看到,join()方法拋出InterruptedException,但我想知道如何清理輔助線程才能正常終止。

這裏的示例程序:

public class Main { 
    public static void main(String[] args) { 
     Thread t = new Thread() { 
      public void run() { 
       while (true) { 
        if (Thread.interrupted()) { 
         break; 
        } 
       } 
       System.out.println("[thread] exiting..."); 
      } 
     }; 

     System.out.println("[main] starting the thread"); 
     t.start(); 
     System.out.println("[main] interrupting the secondary thread"); 
     t.interrupt(); 

     try { 
      t.join(); 
     } catch (InterruptedException e) { 
      Thread.currentThread().interrupt(); 
      throw new RuntimeException(e); 
     } 
     System.out.println("[main] exiting"); 
    } 
} 

這段代碼將打印輸出如下:

[main] starting the thread 
[main] interrupting the secondary thread 
[thread] exiting... 
[main] exiting 

我發現在互聯網上的某些條款(如本http://www.yegor256.com/2015/10/20/interrupted-exception.html)建議將中斷標誌爲true並拋出RuntimeException。我不明白這將如何緩解這種情況(在退出前清理剩餘的線程)。

謝謝。

編輯:代碼剪斷我提到在評論

public class Main { 
    public static void main(String[] args) throws InterruptedException { 
     Thread mainThread = Thread.currentThread(); 
     Thread t = new Thread() { 
      public void run() { 
       while (true) { 
        if (Thread.currentThread().isInterrupted()) { 
         break; 
        } 
       } 
       System.out.println("[thread] interrupting the main thread..."); 
       mainThread.interrupt(); 
       System.out.println("[thread] exiting..."); 
      } 
     }; 

     System.out.println("[main] starting the thread"); 
     t.start(); 
     System.out.println("[main] interrupting the secondary thread"); 
     t.interrupt(); 

     try { 
      t.join(); 
     } catch (InterruptedException e) { 
      System.out.println("[main] InterruptedException indeed happened"); 
      Thread.currentThread().interrupt(); 
      throw e; 
     } 
     System.out.println("[main] exiting"); 
    } 
} 
+0

你把你的線程包裝在任務中並使用該任務的stateProperty()。addListener – kamel2005

+0

只要你的線程t沒有標記爲守護進程,它應該與主程序一起終止。 – kalsowerus

+0

@ kamel2005你能解釋一下你的意思嗎?我想要實現的是主線程將停止長時間運行的輔助線程並正確處理外部中斷/信號。 – Predkambrij

回答

1

在您的例子沒有什麼會中斷主線程,沒有代碼處理InterruptedException從呼叫加入輔助線程上拋出將得到執行。所以這真的沒關係。設置中斷標誌的目的是讓該線程中執行的其他內容知道中斷,因此所有內容都可以退出正在執行的操作,這在這裏不是問題。

您可以將主要方法封裝在一個try-catch塊中,該塊記錄捕獲的任何內容。這是一個正常的事情來確保所有異常都被記錄下來。

您的代碼在輔助線程上調用interrupt。只要該線程被寫入以通過清理和退出來響應中斷,那麼就沒有更多的事情要做。

請勿使用Thread.interrupted(),請使用Thread.currentThread().isInterrupted()。作爲副作用,interrupted方法清除中斷標誌。

捕獲InterruptedException並拋出RuntimeExceptionjava.util.concurrent類的寫入方式不一致。將InterruptedException引發出來比將其包裝在未經檢查的異常中更爲慣用。

示例代碼不能被信號中斷,您必須自己通過編寫自己的信號處理程序來實現該功能。

+0

謝謝你的回答。我擔心的是主線程可能以某種方式被外部程序(例如SIGINT,但事實並非如此)或OS內核中斷。 我設法在終止之前從輔助線程中斷主線程(請參閱在問題結尾添加剪切)。 因此,據我所知,如果沒有輔助線程會中斷主線程,則不會拋出異常? – Predkambrij

+0

@Predkambrij:你可以選擇編寫處理信號和中斷線程的代碼。否則沒有連接。只有當某個線程調用中斷時纔會拋出異常。 –