2011-01-27 34 views
11

我有一個ExecutorService管理許多Callables。 Callables運行的任務主要是黑匣子轉換和數字運算。在某些情況下,正在轉換的數據會振盪,線程將花費一個多小時才能完成。爲了比較,大多數線程在一分鐘內完成。使用ExecutorService的個別線程的時間限制

長期運行的線程的數據並不相關,我想中斷任何運行時間超過一定時間的線程。什麼是最好的方式來做到這一點?

回答

19

當達到超時時,使用ScheduleExecutorService將任務安排到taskFuture.cancel(true)長時間運行的任務。如果任務在此之前完成,則不會被取消。

ExecutorService service = Executors.newFixedThreadPool(N); 
ScheduledExecutorService canceller = Executors.newSingleThreadScheduledExecutor(); 

public <T> Future<T> executeTask(Callable<T> c, long timeoutMS){ 
    final Future<T> future = service.submit(c); 
    canceller.schedule(new Callable<Void>(){ 
     public Void call(){ 
      future.cancel(true); 
      return null; 
     } 
    }, timeoutMS, TimeUnit.MILLI_SECONDS); 
    return future; 
} 
3

要做到這一點,最好的方法是引入一個Executor。您可以使用ScheduledExecutorService的取消所有長時間運行的任務,例如:

ExecutorService service = Executors.newFixedThreadPool(N); 

ScheduledExecutorService canceller = Executors.newScheduledThreadPool(1); 

public void executeTask(Callable<?> c){ 
    final Future<?> future = service.submit(c); 
    canceller.schedule(new Runnable(){ 
     public void run(){ 
      future.cancel(true); 
     } 
    }, SECONDS_UNTIL_TIMEOUT, TimeUnit.SECONDS); 
} 
+0

調用需要返回一個值。 – 2011-01-27 17:58:17

+1

謝謝,你可以想象我只是自由寫作而已。如果只有Firefox有內置編譯器:) – 2011-01-27 17:59:51

0

你可以(當你提交一個Callable創建的),其啓動時間,讓你的相應期貨的名單一起。

然後,另一個任務可以檢查每分鐘是否有某個任務運行超過了定義的時間,如果是,則在未來調用cancel(true)。完成期貨將從名單中刪除。

0

您可以使用此方法

<T> List<Future<T>> invokeAll(Collection<? extends Callable<T>> tasks, 
           long timeout, 
           TimeUnit unit) 
          throws InterruptedException 

和最大超時設置爲一分鐘。如果你的線程需要更多,它只是中止。

5

您可以取消未來等在其他答案,但你需要確保你的線程是「數字計算」可以處理中斷並優雅地終止。你說這是一個黑匣子操作 - 你有多確定線程的中斷狀態正在黑匣子中被主動檢查?如果不是,則不能用中斷取消它。黑盒子需要在中斷的情況下書寫。

相關問題