• java中CompletionService的使用


    java中CompletionService的使用

    之前的文章中我们讲到了ExecutorService,通过ExecutorService我们可以提交一个个的task,并且返回Future,然后通过调用Future.get方法来返回任务的执行结果。

    这种方式虽然有效,但是需要保存每个返回的Future值,还是比较麻烦的,幸好ExecutorService提供了一个invokeAll的方法,来保存所有的Future值,我们看一个具体的实现:

       public void useExecutorService() throws InterruptedException {
            ExecutorService executor = Executors.newFixedThreadPool(10);
    
            Callable<String> callableTask = () -> {
                TimeUnit.MILLISECONDS.sleep(300);
                return "Task's execution";
            };
    
            List<Callable<String>> callableTasks = new ArrayList<>();
            callableTasks.add(callableTask);
            callableTasks.add(callableTask);
            callableTasks.add(callableTask);
    
            List<Future<String>> futures = executor.invokeAll(callableTasks);
    
            executor.shutdown();
    
        }
    

    上面的例子中,我们定义了3个task,通过调用executor.invokeAll(callableTasks)返回了一个 List<Future>,这样我们就可以得到所有的返回值了。

    除了上面的invokeAll方法外,我们今天要介绍一个CompletionService接口。

    CompletionService实际上是ExecutorService和BlockingQueue的结合体,ExecutorService用来提交任务,而BlockingQueue用来保存封装成Future的执行结果。通过调用take和poll的方法来获取到Future值。

    CompletionService是一个接口,我们看下它的一个具体实现ExecutorCompletionService:

        public ExecutorCompletionService(Executor executor) {
            if (executor == null)
                throw new NullPointerException();
            this.executor = executor;
            this.aes = (executor instanceof AbstractExecutorService) ?
                (AbstractExecutorService) executor : null;
            this.completionQueue = new LinkedBlockingQueue<Future<V>>();
        }
    

    ExecutorCompletionService接收一个Executor作为参数。

    我们看下上面的例子如果用ExecutorCompletionService重写是怎么样的:

       public void useCompletionService() throws InterruptedException, ExecutionException {
            ExecutorService executor = Executors.newFixedThreadPool(10);
            CompletionService<String> completionService=new ExecutorCompletionService<String>(executor);
            Callable<String> callableTask = () -> {
                TimeUnit.MILLISECONDS.sleep(300);
                return "Task's execution";
            };
            for(int i=0; i< 5; i ++){
                completionService.submit(callableTask);
            }
    
            for(int i=0; i<5; i++){
                Future<String> result=completionService.take();
                System.out.println(result.get());
            }
        }
    

    上面的例子通过completionService.submit来提交任务,通过completionService.take()来获取结果值。

    其实CompletionService还有一个poll的方法,poll和take的区别在于:take如果获取不到值则会等待,而poll则会返回null。

    本文的例子可以参考https://github.com/ddean2009/learn-java-concurrency/tree/master/CompletionService

    更多内容请访问 flydean的博客

  • 相关阅读:
    jQuery选择器大全
    MVC自定义数据验证(两个时间的比较)
    SQLServer开发总结
    疯狂的订餐系统软件需求分析挑战之旅1
    疯狂的订餐系统软件需求分析挑战之旅2
    net中C#自动化调用Word的实例总结
    软件开发中代码自动化的一点浅见
    代码自动化(1)开篇
    代码自动化(2)程序设计
    Excel 手机号码、身份证 等信息 导入到SQL2005 中,转换成字符是自动变成 科学计数法 的解决方法
  • 原文地址:https://www.cnblogs.com/flydean/p/12680258.html
Copyright © 2020-2023  润新知