2012-04-26 43 views
3

我想在後臺執行一些有時間限制的工作。事情是,我不想阻止主線程。ExecutorService超時而不會阻塞主線程

天真的實現是有兩個執行器服務。一個用於調度/超時,另一個負責完成工作。

final ExecutorService backgroundExecutor = Executors.newSingleThreadExecutor(); 
final ExecutorService workerExecutor = Executors.newCachedThreadExecutor(); 


backgroundExecutor.execute(new Runnable() { 
    public void run() { 
     Future future = workerExecutor.submit(new Runnable() { 
      public void run() { 
       // do work 
      } 
     }); 
     try { 
      future.get(120 * 1000, TimeUnit.MILLISECONDS); 
     } catch (InterruptedException e) { 
      logger.error("InterruptedException while notifyTransactionStateChangeListeners()", e); 
      future.cancel(true); 
     } catch (ExecutionException e) { 
      logger.error("ExecutionException", e); 
     } catch (TimeoutException e) { 
      logger.error("TimeoutException", e); 
      future.cancel(true); 
     } 
    } 
}); 

還有其他解決方案嗎?

+0

一個簡單化將是一個單線程池,其中一個線程執行作業,另一個線程池等待它。這至少可以拯救內部泳池,但除此之外沒有太大的幫助。 – Gray 2012-04-26 13:02:57

+0

是否有可能同時向定時器和執行器發佈任務?其中一個將首先進入run(),因此需要在某個地方進行鎖定或同步,以便在超時和任務完成之間進行仲裁,以便在每種情況下都能採取正確的操作。嗯..不知道。 – 2012-04-26 13:07:24

+0

由於您在代碼中忽略Future.get()的結果,我不知道您是否真的需要等待某個線程中的結果? – 2012-04-27 04:11:36

回答

2

你不需要一個ExecutorService只是一次運行一個單獨的線程。您可以創建一個FutureTask,它可以爲您提供相同的好處,而不會產生開銷。

FutureTask<T> future = new FutureTask<T>(callable); 
Thread thread = new Thread(future); 
thread.start(); 
try { 
    future.get(120 * 1000, TimeUnit.MILLISECONDS); 
} ... 

在上面的代碼片段中可調用將是你的任務。 如果你有一個Runnable(如你在上面的代碼塊做),你可以通過把它變成一個可贖回:

Callable callable = Executors.callable(runnable, null); 

所以,總結一下,你的代碼可以改變爲:

backgroundExecutor.execute(new Runnable() { 
    public void run() { 

     Runnable myRunnable = new Runnable() { 
      public void run() { 
       // do work 
      } 
     } 

     Callable callable = Executors.callable(myRunnable, null); 

     FutureTask<T> future = new FutureTask<T>(callable); 
     Thread thread = new Thread(future); 
     thread.start(); 

     try { 
      future.get(120 * 1000, TimeUnit.MILLISECONDS); 
     } catch (InterruptedException e) { 
      logger.error("InterruptedException while notifyTransactionStateChangeListeners()", e); 
      future.cancel(true); 
     } catch (ExecutionException e) { 
      logger.error("ExecutionException", e); 
     } catch (TimeoutException e) { 
      logger.error("TimeoutException", e); 
      future.cancel(true); 
     } 
    } 
}); 

你不需要最後關閉執行程序。儘管你可能仍然希望最終清理任何其他資源。

相關問題