invokeAll和CompletionService

需求场景:服务A依赖于其他三个服务:服务B、服务C、服务D,而服务A的调用方要求服务A在100ms内返回结果。服务A需要在100ms内把已经有结果的服务返回,取消无结果的服务。

使用ExecutorService.invokeAll()方法,该方法输入是一个Callable任务的集合,返回的是Future集合,Future集合的顺序与输入的任务一样。invokeAll()的超时时限是对这一整组集合来说的。
该方法会阻塞,当所有任务执行完毕或者超时的时候,方法就会返回,若有未完成的任务,invokeAll()方法中会调用cancel(true)方法来取消任务。我们可以对返回的Future调用isCancelled()方法来看该任务是否已经执行完毕。

    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:需要等全部任务执行完毕或者超时再返回

    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
posted @ 2018-01-22 14:00  水煮海鲜  阅读(252)  评论(0编辑  收藏  举报