2009-11-30 54 views
4

我正在運行一個線程,其主要操作是使用阻塞函數調用代理,然後等待它給它一些東西。中斷等待阻塞操作的線程?

我用揮發性布爾和中斷已知的模式,但我不知道它會工作:當我試圖添加一個catch塊爲InterruptedException,我得到的錯誤:

Unreachable catch block for InterruptedException. This exception is never thrown from the try statement body

所以如果我永遠不會得到InterruptedException,這意味着我永遠不會走出阻塞行動 - 因此永遠不會停止。

我有點困惑。任何想法?

public void run() {  
    Proxy proxy = ProxyFactory.generateProxy(); 
    Source source; 

    while (!isStopped) { 
     try { 
     source = proxy.getPendingSources(); 
     scheduleSource(source); 
     } catch (Exception e) { 
     log.error("UnExpected Exception caught while running",e); 
     } 
    } 
    } 

    public void stop() { 
    this.isStopped = true; 
    Thread.currentThread().interrupt(); 
    } 

回答

11

首先,你並不需要一個單獨的標誌(如果你這樣做,使用AtomicBoolean),只需檢查Thread.currentThread().isInterrupted()作爲你的條件。

其次,您的停止方法將不起作用,因爲它不會中斷正確的線程。如果另一個線程調用停止,代碼使用Thread.currentThread()這意味着調用線程將被中斷,而不是正在運行的線程。

最後,什麼是阻塞方法?是scheduleSource()?如果該方法沒有拋出InterruptedException,那麼您將無法捕捉到它。

嘗試以下操作:

private final AtomicReference<Thread> currentThread = new AtomicReference<Thread>(); 

public void run() { 
    Proxy proxy = ProxyFactory.generateProxy(); 
    Source source; 

    currentThread.set(Thread.currentThread()); 

    while (!Thread.currentThread().isInterrupted()) { 
     try { 
      source = proxy.getPendingSources(); 
      scheduleSource(source); 
     } catch (Exception e) { 
      log.error("UnExpected Exception caught while running", e); 
     } 
    } 
} 

public void stop() { 
    currentThread.get().interrupt(); 
} 
+0

謝謝!這花了我幾分鐘,但我意識到我在「停止」方面做了什麼錯誤。 在這種情況下,如果線程將得到「停止」請求,它將停止等待阻止操作? – Yossale 2009-11-30 15:55:35

+0

或者更好的只是使用一個易變的布爾值標記停止。 – 2009-11-30 16:10:47

+1

@Tom如果scheduleSource()或proxy.getPendingSources()被封鎖了怎麼辦?我假設他會希望這個調用被stop()中斷() – Kevin 2009-11-30 16:13:31

1

你是如何從執行線程調用stop的?
如果你從另一個線程調用stop(),你會殺死它,而不是在try/catch塊中運行的線程。

2

stop方法是錯誤的線程上調用interruptThread.currentThread()是中斷,不被中斷的線程。

10

只有少數定義明確的「阻止方法」是可中斷的。如果一個線程被中斷,一個標誌被設置,但是除非線程到達這些明確定義的中斷點之一,否則不會發生任何其他事件。

例如,如果read()write()呼叫在使用InterruptibleChannel創建的流上調用,則這些呼叫是可中斷的。如果使用Socket作爲起點,則在Thread上調用interrupt()將無法​​讀取。請注意,如果阻止I/O操作成功中斷,則底層通道將關閉。

另一大類的可中斷操作是由java.util.concurrent包中的各類阻塞操作引發的。當然,原始的wait()方法也是可以中斷的。

可以通過在其方法簽名中查找throws InterruptedException來識別阻塞方法。他們也應該有充分的文件來描述任何中斷的副作用。

你可以自己寫一個可中斷的方法,但它必須由可中斷的低級操作本身組成。

+0

爲了編寫一個可中斷的方法,它當然可以定期測試'Thread#interrupted()'並且拋出'InterruptedException'在一個其他長時間運行的方法中 - 尤其是涉及循環的方法,如果在該循環中沒有被調用的方法本身是可中斷的,則經常測試中斷。 – seh 2009-11-30 20:43:33

2

好吧,人們,不要殺了我。

爲了好玩,我嘗試了Thread.stop(),將線程踢出阻塞動作,捕獲ThreadDeath,使目標線程保持活動狀態,然後繼續。

它似乎工作。世界沒有結束。但我只是說。你對你自己的行爲負責。我爲什麼要說唱?