需求场景:服务A依赖于其余三个服务:服务B、服务C、服务D,而服务A的调用方要求服务A在100ms内返回结果。服务A须要在100ms内把已经有结果的服务返回,取消无结果的服务。this
使用ExecutorService.invokeAll()方法,该方法输入是一个Callable任务的集合,返回的是Future集合,Future集合的顺序与输入的任务同样。invokeAll()的超时时限是对这一整组集合来讲的。
该方法会阻塞,当全部任务执行完毕或者超时的时候,方法就会返回,如有未完成的任务,invokeAll()方法中会调用cancel(true)方法来取消任务。咱们能够对返回的Future调用isCancelled()方法来看该任务是否已经执行完毕。code
public void testCustomerExecutorException() { List<SayHello> tasks = Lists.newArrayList(); for (int i = 5; i >= 1; i--) { tasks.add(new SayHello(i)); } List<Future<String>> futures = Lists.newArrayList(); try { futures = fixedExecutorService.invokeAll(tasks, 250, TimeUnit.MILLISECONDS); } catch (Exception e) { System.out.println("Main: " + e); } for (Future<String> future :futures) { try { String s = future.get(); System.out.println("get ok: " + s); } catch (Exception e) { System.out.println("get error: " + e); } } } private class SayHello implements Callable<String> { private int id; public SayHello(int id) { this.id = id; } public String call() throws Exception { try { Thread.sleep(id*100); } catch (Exception e) { System.out.println(id + "; SayHello: " + e); return "hello " + id; } return "hello " + id; } }
CompletionService与invokeAll的不一样点在于:
CompletionService:任务执行完毕立刻返回
invokeAll:须要等所有任务执行完毕或者超时再返回get
public ExecutorService fixedExecutorService = Executors.newFixedThreadPool(5); private final BlockingQueue<Future<String>> queue = new LinkedBlockingDeque<Future<String>>(10); private final CompletionService<String> completionService = new ExecutorCompletionService<String>(fixedExecutorService, queue); public void testCustomerExecutorException() { for (int i = 5; i >= 1; i--) { completionService.submit(new SayHello(i)); } for (int i = 0; i < 5; i++) { try { //谁最早执行完成,直接返回 Future<String> f = completionService.take(); System.out.println(f.get()); } catch (Exception e) { } } } private class SayHello implements Callable<String> { private int id; public SayHello(int id) { this.id = id; } public String call() throws Exception { try { Thread.sleep(id*100); } catch (Exception e) { return "hello " + id; } return "hello " + id; } } //输出 //hello1 //hello2 //hello3 //hello4 //hello5