簡體   English   中英

Java:當被另一個線程中斷時,如何在線程上捕獲InterruptedException?

[英]Java: How do I catch InterruptedException on a thread, when interrupted by another thread?

我正在開發一個多線程應用程序來連接外部服務器 - 每個都在不同的線程上 - 並且會被阻塞直到有輸入。 其中每個都擴展了Thread類。 為了便於解釋,我們稱之為“連接線程”。

所有這些連接線程都存儲在並發hashmap中。

然后,我允許RESTful Web服務方法調用取消任何線程。 (我正在使用Grizzly / Jersey,所以每次調用都是一個線程。)

我檢索特定的連接線程(來自hashmap)並在其上調用interrupt()方法。

那么,這是一個問題,在連接線程中,我如何捕獲InterruptedException? (當外部RESTful命令停止連接線程時,我想做點什么。)

那么,這是一個問題,在連接線程中,我如何捕獲InterruptedException?

你不能。 由於如果您的線程在讀取I / O操作中被阻止,則無法interrupted 這是因為interrupt只是設置一個標志來指示線程已被中斷。 但是如果您的線程已被I / O阻塞,它將看不到該標志。
正確的方法是關閉底層套接字(線程被阻塞),然后捕獲異常並將其傳播。
因此,由於您的連接線程extend Thread請執行以

@Override  
public void interrupt(){  
   try{  
      socket.close();  
   }  
   finally{  
     super.interrupt();  
   }  
}   

這樣就可以中斷I / O上阻塞的線程。

然后在你的run方法中執行:

@Override  
public void run(){  

    while(!Thread.currentThread().isInterrupted()){    
       //Do your work

    }  
}    

所以在你的情況下不要試圖catch InterruptedException 您無法中斷I / O上阻塞的線程。 只需檢查您的線程是否已被中斷,並通過關閉流來促進中斷。

阻塞的問題。

Hoverer,試試這個代碼,也許它會幫助你:

try{
 yourObject.read();
}catch(InterruptedException ie){
// interrupted by other thread
}
catch(Exception ex){
// io or some other exception happent
}

你的讀取方法,應該檢查插座上是否有可用的買入物,例如,如果還有讀取它,則其他選擇去拼寫模式。 當睡眠時間超過可用時,在pur套接字讀取喚醒(InterruptedException)(無論讀取什么)它將被阻止。 某些API具有最大等待值,例如5秒60秒,如果沒有讀取,則將執行下一個代碼。

class MyReadingObject
{
   public read() throws InterruptedException{
      while(shouldIread){
        if(socket.available() > 0){
           byte[] buff = new byte[socket.avaialble()]
           socket.read(buff);
           return;
        }
        else{
           Thread.currentThread.sleep(whateverMilliseconds);
        } 
     }
  }
}

類似的東西,但有錯誤處理和一些設計模式

當你在某個線程上調用Thread.interrupt()時,會發生的是為該線程設置'interruption'標志。 有些方法檢查此標志(通過Thread.interrupted()Thread.isInterrupted() )並拋出InterruptedException ,但通常只有可以阻止的方法執行此操作。 因此,有沒有保證InterruptedException永遠不會在中斷線程被拋出。 如果你沒有調用任何拋出InterruptedException方法,那么捕獲該異常是沒有意義的,因為它根本不會被拋出。 但是,您始終可以通過調用Thread.isInterrupted()來檢查您的線程是否被中斷。

在線程上調用interrupt()不會停止它,它只是打開中斷標志。 代碼負責處理所考慮的線程的中斷狀態的變化並相應地采取行動。 如果您正在該線程中執行阻塞操作,那么您幾乎是SOL,因為您的線程在讀取時“阻塞”。 看看我在這里發布的答案。 所以基本上,除非你循環遍歷東西或定期檢查該線程中的一些標志,否則你無法在沒有關閉套接字或類似東西的情況下爆發。

這里的一個解決方案是“顯式”公開底層連接對象並在其上調用close() ,強制它拋出某種異常,然后可以在線程代碼中處理。 就像是:

class MyAction extends Thread implements Disposable {

  public void doStuff() {
    try {
      byte[] data = this.connection.readFully();
  } catch (InterruptedException e) {
    // possibly interrupted by forceful connection close    
  }

  @Override
  public void dispose() {
    this.connection.close();
  }
}

// Elsewhere in code
MyAction action = conMap.get("something");
action.dispose();

像這樣使用try-catch:

try {
    //code
} catch ( InterruptedException e) {
    //interrupted
}

我認為應該做的伎倆,你也可以保留一個布爾變量是否退出,所以他們會檢查該變量,如果它是真的,停止

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM