首页 > 其他分享 >CompletionService 使用小结

CompletionService 使用小结

时间:2022-12-04 21:57:05浏览次数:49  
标签:异步 CompletionService get futures 任务 使用 FutureTask 小结

本文为博主原创,转载请注明出处:

  实现异步任务时,经常使用 FutureTask 来实现;一个简单的示例代码如下:

public static void main(String[] args) throws ExecutionException, InterruptedException {
        //构建线程池
        ExecutorService executorService = Executors.newFixedThreadPool(2);
        FutureTask<Integer> futureTask1 = (FutureTask<Integer>) executorService.submit(()->doTask1());
        FutureTask<Integer> futureTask2 = (FutureTask<Integer>) executorService.submit(()->doTask2());

        //    获取电结果并异步保存
        executorService.execute(()->save(futureTask1.get()));
        //    获取结果并异步保存
        executorService.execute(()->save(futureTask2.get());
         
    }

  上面代码如果 futureTask1 的任务需要执行很长时间,而 futureTask2 执行很短时间,上面代码在执行的过程中,futureTask2 任务的执行也的先等 futureTask1.get() 执行结束后 ,才能保存 futureTask2.get() ;因为这个主线程都阻塞在 futureTask1.get() 的操作上;严重降低了效率。

  此时可以使用 CompletionService 来解决这个问题

  CompletionService 接口的功能是以异步的方式一边生产新的任务,一边处理已完成任务的结果,这样就可以将执行任务与处理任务分离开。

  CompletionService的一个实现是ExecutorCompletionService,它是Executor和BlockingQueue功能的融合体,Executor完成计算任务,BlockingQueue负责保存异步任务的执行结果;先执行完的先进入阻塞队列,利用这个特性,你可以轻松实现后续处理的有序性,避免无谓的等待。在执行大量相互独立和同构的任务时,可以使用CompletionService;

  该实现类定义的三个属性:

  在类的注释上有使用的示例,可以参考学习

  使用 CompletionService 实现的示例如下:

 public static void main(String[] args) {
        // 创建线程池
        ExecutorService executor = Executors.newFixedThreadPool(3);
        // 创建CompletionService
        CompletionService<Integer> cs = new ExecutorCompletionService<>(executor);
        // 用于保存Future对象
        List<Future<Integer>> futures = new ArrayList<>(3);
        //提交异步任务,并保存future到futures
        futures.add(cs.submit(()->doTask1()));
        futures.add(cs.submit(()->doTask2()));
        futures.add(cs.submit(()->doTask3()));
        // 获取最快返回的任务执行结果
        Integer r = 0;
        try {
            // 只要有一个成功返回,则break
            for (int i = 0; i < 3; ++i) {
                r = cs.take().get();
                //简单地通过判空来检查是否成功返回
                if (r != null) {
                    break;
                }
            }
        } finally {
            //取消所有任务
            for(Future<Integer> f : futures)
                f.cancel(true);
        }
        // 返回结果
    }

 

 

  

标签:异步,CompletionService,get,futures,任务,使用,FutureTask,小结
From: https://www.cnblogs.com/zjdxr-up/p/16950918.html

相关文章

  • Android 开启 viewBinding,减少 findViewById 语句的使用
    找到build.gradle文件,因为有两个build.gradle,我们要操作的是第二个:在这个位置加上这一句话,然后点击右上角的SyncNow按钮更新项目:viewBinding{enabled=tr......
  • SpringBoot中使用Spring Data JPA
    Springboot中如何集成springdatajpa一什么是ORM?ORM即Object-RelationlMapping,它的作用是在关系型数据库和对象之间作一个映射,这样,我们在具体的操作数据库的时候,就不需......
  • JDK中内嵌JS引擎介绍及使用
    原文:JDK中内嵌JS引擎介绍及使用-Stars-One的杂货小窝最近研究阅读这个APP,其主要功能就是通过一个个书源,从而实现移动端阅读的体验比如说某些在线小说阅读网站,会加......
  • SpringBoot中使用Spring Data JPA
    Springboot中如何集成springdatajpa一什么是ORM?ORM即Object-RelationlMapping,它的作用是在关系型数据库和对象之间作一个映射,这样,我们在具体的操作数据库的时......
  • Django中使用django_table2如何加一列操作
    要加入列需要自定义一个列,doc中给出如下的例子:>>>fromdjango.utils.safestringimportmark_safe>>>fromdjango.utils.htmlimportescape>>>>>>classImageColu......
  • 如何使用Redis做缓存
    如何使用Redis做缓存我们都知道Redis作为NoSql数据库的代表之一,通常会用来作为缓存使用。也是我在工作中通常使用的缓存之一。1、我们什么时候缓存需要用到Redis?我认为,......
  • Blazor和Vue对比学习(进阶.路由导航一):基本使用
    Blazor和Vue都是单文件组件SPA,路由的实现逻辑非常相似,页面路径的改变都是组件的切换,但因为各自语言的特性,在实现方式上有较大差异。 一、安装1、Vue:Router是Vue的一个......
  • SpringBoot 缓存注解的使用
    最近比较忙,没时间更新了。上一篇文章我说了如何使用Redis做缓存,文末我稍微提到了SpringBoot对缓存的支持。本篇文章就针对SpringBoot说一下如何使用。1、SpringBoot对缓存......
  • 使用burpsuite抓不到火狐的数据包
    首先打开准备好的burpsuite,一直下一步然后点击Proxy代理,点击下辖的Options选项如果你的界面空白如下图那么你需要配置ProxyListeners点击左侧的添加配置端口即可8080,然后......
  • 原生axjax 和axio的结合使用
    固定请求地址和方法<body><script>/*1.新闻接口gethttp://ajax-api.itheima.net/api/news无参数*/functio......