2014-01-11 30 views
6

我有一系列使用ExecutorService排隊的作業。如果用戶點擊'取消',那麼我需要通知那些他們應該儘快停止的工作。但是,有時它們處於父線程繼續執行之前必須完成的關鍵代碼段。我怎樣才能做到這一點?我不想使用自己的取消標誌,因爲這不會導致睡眠/等待退出。如何打斷未來,但仍然等待它完成?

我想這段代碼工作,但它並沒有做什麼,我想:

while(true) { 
    //Do this in a loop. If our thread is interrupted, we call cancel on the threads (to try to get them to hurry up by skipping non-essential stuff), but we still need to wait for them to finish. 
    try { 
     for(Future<Void> future : futures) { 
      future.get(); //I thought that this would continue waiting, even if I call cancel, but it doesn't. How can I wait for the future to finish? 
     } 
     break; //OK, everything is finished, exit the wait loop. 
    } catch(InterruptedException e) { 
     wasInterrupted = true; //We'll rethrow the exception laster as an AbortException. 
     //Need to wait for futures to finish, even if it's canceled. 
     log.info("Attempting to interrupt threads that are reading changes..."); 
     for(Future<Void> future : futures) { 
      future.cancel(true); //I want to tell the threads to 'hurry up' and skip non-essential stuff. 
     } 
    } catch(ExecutionException e) { 
     throw e.getCause(); 
    } 
} 

//I shouldn't get to this line until all futures have finished! 

回答

4

如何打斷未來,但仍然等待它完成?

有趣的問題。您的代碼將不起作用,因爲當您取消Future時,正如您發現的那樣,您不能再次致電get(),因爲這會引發CancellationException

如果我理解你的要求:

  • 你需要能夠中斷線程,因爲你要停止sleepwait等。
  • 你仍然希望能夠得到任務結果取消後。

在做的事情是使用Future這兒。要改爲使用自己的作業包裝並等待ExecutorService本身以executorService.awaitTermination(...)完成。

如果您需要任務的結果,那麼Runnable包裝類將保存計算結果,並且會有boolean done標誌。等待線程將等待每個Runnabledone標誌設置爲true。當包裝完成其run()方法時,它會自行設置donenotify()。這需要在finally區塊中完成。

如果等待線程中斷,它會調用executorService.shutdownNow(true)中斷所有線程,但會繼續循環等待它們完成。

就是這樣的。

+0

這是一個很好的解決方案。我不知道executorService.awaitTermination()方法;這正是我需要的。 –

+0

但是,我不明白關於使用自己的工作包裝的部分。在我的情況下,我不需要結果 - 我只需要等待線程完成 - 所以這不會影響我。但我很好奇你如何在不使用Future對象的情況下使用ExecutorService。這不是提交任務的唯一API嗎? –

+0

所以,如果你不需要結果,那就更簡單了。如果你調用'submit(...)',那麼你得到一個'Future',但你也可以調用'execute(...)'返回'void',並且不會生成一個內部的'FutureTask' @JesseBarnum。 – Gray

0

「儘快」是指該線程應該知道什麼時候退出

反正你可以使用中斷線程政策

if (Thread.interrupted()) // Clears interrupted status! 
     throw new InterruptedException(); 

又見

http://www.ibm.com/developerworks/java/library/j-jtp05236/index.html?ca=drs-

+3

工作線程知道何時退出。問題是父線程不知道要等多久,因爲一旦取消被調用,Future.get()不會被阻塞。 –