• 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的博客

  • 相关阅读:
    CentOS7安装minio
    xshell连接虚拟机Connection failed
    Mysql时间加减函数
    mysql存储过程模板
    Activiti实现会签功能
    2018考研复试流程
    C编程经验总结5(剧终)
    《数据结构总结》
    《关于安卓和IOS开发》
    番外特别篇之 为什么我不建议你直接使用UIImage传值?--从一个诡异的相册九图连读崩溃bug谈起
  • 原文地址:https://www.cnblogs.com/flydean/p/12680258.html
Copyright © 2020-2023  润新知