2016-09-14 271 views
0

我试图实现一个功能,其中或者可以在规定的时间内完成可调参数或者操作超时。我曾希望ExecutorService.awaitTermination()会这样做,但很惊讶地发现它没有。代码如下。运行永不完成。ExecutorService.awaitTermination()永不超时

public class Counter implements Callable<Void> { 

    public static void main(String[] args) throws InterruptedException { 
     final Map<String, Counter> map = new HashMap<>(); 
     map.put("", new Counter()); 
     final Map<String, Future<Void>> result = executeTasksInParallel(map); 
     final Future<Void> voidFuture = result.get(""); 
     try { 
      voidFuture.get(); 
     } catch (Exception e) { 
      e.printStackTrace(); 
     } 
    } 

    @Override 
    public Void call() throws Exception { 
     for (long i = 0L; i < Long.MAX_VALUE; i++); 
     return null; 
    } 

    public static <K, V> Map<K, Future<V>> executeTasksInParallel(final Map<K, ? extends Callable<V>> callablesById) throws InterruptedException { 
     final Map<K, Future<V>> resultFuturesById = new HashMap<>(); 
     final ExecutorService executorService = Executors.newFixedThreadPool(callablesById.size()); 
     for (final Map.Entry<K, ? extends Callable<V>> callableByIdEntry : callablesById.entrySet()) { 
      final K id = callableByIdEntry.getKey(); 
      final Callable<V> callable = callableByIdEntry.getValue(); 
      final Future<V> resultFuture = executorService.submit(callable); 
      resultFuturesById.put(id, resultFuture); 
     } 
     executorService.shutdown(); 
     executorService.awaitTermination(5L, TimeUnit.SECONDS); 
     return resultFuturesById; 
    } 
} 

我在这里错过了什么吗?谢谢!

UPDATE:

我试着用下面替换try块内容,以堵塞避免的Future.get(),但是这并没有帮助

if (voidFuture.isDone()) { 
    voidFuture.get(); 
} 
+0

介意分享了downvote这样我可以提高我在未来的问题的原因是什么? – mindreader

回答

2
  1. 使用shutdownNow()乔C已指定...
  2. ...但它只会通过检查当前线程的工作,如果你在call()代码允许它,例如被中断。见例如this question及其答案的详细信息。如果通过抛出InterruptedException(例如Thread.sleep(...)Object.wait(...),Future.get(...),对实现了InterruptibleChannel等的通道进行阻塞操作),有时您可能会在循环中直接或间接调用处理中断请求的方法, 。 编辑: ...并且如果InterruptedException被抛出不被抑制。
  3. 是的,如果将来isDone()(因为它的主线程不是由您的executorService管理),只能拨打get()

最终代码会

public class Counter implements Callable<Void> { 

    public static void main(String[] args) throws InterruptedException { 
     final Map<String, Counter> map = new HashMap<>(); 
     map.put("", new Counter()); 
     final Map<String, Future<Void>> result = executeTasksInParallel(map); 
     final Future<Void> voidFuture = result.get(""); 
     try { 
      if (voidFuture.isDone()) { 
       voidFuture.get(); 
      } 
     } catch (Exception e) { 
      e.printStackTrace(); 
     } 
    } 

    @Override 
    public Void call() throws Exception { 
     for (long i = 0L; i < Long.MAX_VALUE; i++) { 
      if (Thread.currentThread().isInterrupted()) { 
       Thread.currentThread().interrupt(); // restore interrupted flag 
       return null; 
      } 
      /* or e.g. throw an exception */ 
     } 
     return null; 
    } 

    public static <K, V> Map<K, Future<V>> executeTasksInParallel(
      final Map<K, ? extends Callable<V>> callablesById) 
      throws InterruptedException { 
     final Map<K, Future<V>> resultFuturesById = new HashMap<>(); 
     final ExecutorService executorService = 
      Executors.newFixedThreadPool(callablesById.size()); 
     for (final Map.Entry<K, ? extends Callable<V>> callableByIdEntry : callablesById 
      .entrySet()) { 
      final K id = callableByIdEntry.getKey(); 
      final Callable<V> callable = callableByIdEntry.getValue(); 
      final Future<V> resultFuture = executorService.submit(callable); 
      resultFuturesById.put(id, resultFuture); 
     } 
     executorService.shutdown(); 
     executorService.awaitTermination(5L, TimeUnit.SECONDS); 
     executorService.shutdownNow(); 
     return resultFuturesById; 
    } 
} 
+1

我对#2的措辞有个小问题:即使代码调用睡眠或等待等,它仍然可以以相反的方式压制InterruptedException。仍然是+1。 –

+0

谢谢!这非常有帮助。 – mindreader

0

文件awaintTermination的:

阻塞,直到关闭请求或超时发生后所有任务都已完成执行,或当前线程中断,以先发生者为准。

它会在5秒后完成,但生成的线程仍然在工作,它不是一个守护进程线程,所以你的代码将继续工作,直到子线程终止。

voidFuture.get()将会阻塞直到返回。

+0

感谢您的回应!我想要实现的是可调用标记应该被标记为超时,并且应该在这样的事件中抛出异常。你能告诉我如何实现这一目标吗? – mindreader

+0

另外,我有点困惑,因为ExecutorService.awaitTermination()似乎没有实现任何东西。 – mindreader