2013-04-29 150 views
3

我在探索ExecutorService時,遇到方法Future.get(),它接受timeout執行程序服務 - 線程超時

這種方法的Java的醫生說


如有必要,等待至多給定的時間計算完成,然後獲取其結果(如果可用)。

參數:

超時的最長等待時間

單元超時參數


按我理解的時間單位,我們正在實行超時callable,我們提交到ExecutorService這樣,我的callable中斷已超過指定時間(超時)

但根據以下代碼,longMethod()似乎超出超時(2秒),我真的很困惑理解這一點。任何人都可以請我指出正確的道路?

import java.util.concurrent.Callable; 
import java.util.concurrent.ExecutorService; 
import java.util.concurrent.Executors; 
import java.util.concurrent.TimeUnit; 

public class Timeout implements Callable<String> { 

    public void longMethod() { 
     for(int i=0; i< Integer.MAX_VALUE; i++) { 
      System.out.println("a"); 
     } 
    } 

    @Override 
    public String call() throws Exception { 
     longMethod(); 
     return "done"; 
    } 


    /** 
    * @param args 
    */ 
    public static void main(String[] args) { 
     ExecutorService service = Executors.newSingleThreadExecutor(); 

     try { 
      service.submit(new Timeout()).get(2, TimeUnit.SECONDS); 
     } catch (Exception e) { 
      e.printStackTrace(); 
     } 
    } 


} 
+2

除了答案之外,請注意即使任務被中斷,因爲它永遠不會檢查中斷標誌,它會繼續運行直到結束。 – 2013-04-29 11:17:59

回答

12

我贖回已通過

不是真的在規定時間(超時)後會中斷。該任務將繼續執行,而在超時後您將擁有一個空字符串。

如果你想取消:

timeout.cancel(true) //Timeout timeout = new Timeout(); 

附:正如你現在這樣,這個中斷不會有什麼影響。你沒有以任何方式檢查它。

例如這段代碼考慮中斷:

private static final class MyCallable implements Callable<String>{ 

    @Override 
    public String call() throws Exception { 
     StringBuilder builder = new StringBuilder(); 
     try{ 
      for(int i=0;i<Integer.MAX_VALUE;++i){ 
       builder.append("a"); 
       Thread.sleep(100); 
      } 
     }catch(InterruptedException e){ 
      System.out.println("Thread was interrupted"); 
     } 
     return builder.toString(); 
    } 
} 

然後:

 ExecutorService service = Executors.newFixedThreadPool(1); 
    MyCallable myCallable = new MyCallable(); 
    Future<String> futureResult = service.submit(myCallable); 
    String result = null; 
    try{ 
     result = futureResult.get(1000, TimeUnit.MILLISECONDS); 
    }catch(TimeoutException e){ 
     System.out.println("No response after one second"); 
     futureResult.cancel(true); 
    } 
    service.shutdown(); 
+1

在你的Callable中使用Thread.currentThread()。isInterrupted()(或Thread.currentThread()。interrupted())來檢查Future.cancel是否被調用。如果你的可卡因不長時間運行,這可能不是必要的,但對於長時間運行的可卡因,這將允許你在必要時乾淨地關閉線程。 – wort 2013-04-29 12:04:42

2

上的get()的超時爲「客戶」多久將等待未來完成。它對未來的執行沒有影響。

Object result; 
int seconds = 0; 
while ((result = fut.get.(1, TimeUnit.SECOND)) == null) { 
    seconds++; 
    System.out.println("Waited " + seconds + " seconds for future"; 
} 
0

我調用將已通過

上述說法是錯誤的指定時間(超時)後中斷,通常的Future.get阻止。指定超時允許您以非阻塞的方式使用它。

這對於時間關鍵型應用程序很有用,如果您需要一個結果,比如說2秒,那麼接收之後意味着您無法做任何事情。