![](/img/trans.png)
[英]Do the BlockingQueue methods always throw an InterruptedException when the thread is interrupted?
[英]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.