2013-04-29 117 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秒,那么接收之后意味着您无法做任何事情。