美文网首页
CompletionService批量执行异步任务

CompletionService批量执行异步任务

作者: 刘彦青 | 来源:发表于2019-09-25 10:47 被阅读0次

CompletionService的实现原理也是内部维护了一个阻塞队列,当任务执行结束就把任务的执行结果加入到 阻塞队列中,不同的是CompletionService是把任务执行结果的Future对象加入到阻塞队列中

CompletionService能做什么?

将异步任务的结果保存到队列中,主线程从队列中取出这些结果数据执行。

场景: 向不同电商平台询价,并保存价格

采用“ThreadPoolExecutor+Future”的方案:异步执行询价然后再保存

//  创建线程池 
ExecutorService executor = Executors.newFixedThreadPool(3); 
//  异步向电商S1询价 
Future<Integer> f1 = executor.submit(()->getPriceByS1()); 
//  异步向电商S2询价 
Future<Integer> f2= executor.submit(()->getPriceByS2());            
//  获取电商S1报价并异步保存 
executor.execute(()->save(f1.get()));       
//  获取电商S2报价并异步保存 
executor.execute(()->save(f2.get())     

这个如果获取电商S1报价的耗时很长,那么即便获取电商S2报价的耗时很短,也无法让保存S2报价的操作先执行,因为这个主线程都阻塞 在了f1.get()操作上。这点小瑕疵你该如何解决呢?

增加一个阻塞队列,获取到S1、S2的报价都进入阻塞队列,然后在主线程中消费阻塞队列,这样就能保证先获取到的报价先保存到数据库了。Java并发工具库中的CompletionService就能实现这个方案。

创建CompletionService

ExecutorCompletionService是CompletionService接口的实现类,这个实现类的构造方法有两个:

//一,默认会使用无界的 LinkedBlockingQueue
ExecutorCompletionService (Executor executor)
//二,可以自定义队列    
ExecutorCompletionService (Executor executor,BlockingQueue<Future<V>> completionQueue)

示例:

//  创建线程池 
ExecutorService executor =  Executors.newFixedThreadPool(10); 
//  创建CompletionService 
CompletionService<Integer> cs = new ExecutorCompletionService<>(executor); 
//  异步向电商S1询价 
cs.submit(()->getPriceByS1()); 
//  异步向电商S2询价 
cs.submit(()->getPriceByS2()); 
//  异步向电商S3询价 
cs.submit(()->getPriceByS3()); 
//  将询价结果异步保存到数据库 
for (int i=0; i<3;i++)  {       
    Integer r = cs.take().get();
    executor.execute(()->save(r)); 
}

CompletionService API

提交相关的api

//  提交Callable任务
Future<V> submit(Callable<V> task); 
//  提交Runnable任务及结果引⽤
Future<V> submit(Runnable task, V result); 

阻塞相关api

//从阻塞队列中获取并移除一个元素,如果阻塞队列是空的,调用take()方法的线程会被阻塞
Future<V>   take() throws InterruptedException; 
//从阻塞队列中获取并移除一个元素,如果阻塞队列是空的返回null
Future<V>   poll(); 
/**
 *从阻塞队列中获取并移除一个元素,如果阻塞队列是空等待了timeout unit时间,阻塞队列还是空的,
 *那么该方法会返回null值。
 */
Future<V>   poll(long timeout, TimeUnit unit) throws InterruptedException;

总结

  • 当需要批量提交异步任务的时候建议你使用CompletionService。
  • CompletionService将线程池Executor和阻塞队列BlockingQueue的功能融合在了一起,能够让批量异步任务的管理更简单。
  • CompletionService能够让异步任务的执行结果有序化,先执行完的先进入阻塞队列,利用这个特性,你可以轻松实现后续处理的有序性,避免无谓的等待,同时还可以快速实现诸如Forking Cluster这样的需求。
  • CompletionService的实现类ExecutorCompletionService,需要你自己创建线程池,虽看上去有些啰嗦,但 好处是你可以让多个ExecutorCompletionService的线程池隔离,这种隔离性能避免几个特别耗时的任务拖垮整个应用的风险。

**** 码字不易如果对你有帮助请给个关注****

**** 爱技术爱生活 QQ群: 894109590****

相关文章

  • CompletionService批量执行异步任务

    CompletionService的实现原理也是内部维护了一个阻塞队列,当任务执行结束就把任务的执行结果加入到 阻...

  • 异步任务批量执行

    结果:0314526789 为什么要批量执行? 看下面的代码说明: 执行结果:thread1thread2 ...

  • 周总结-JS依次执行多项异步任务

    1、JS依次执行多项异步任务 有时候,我们希望批量执行一组异步任务,但是不是并行,而是依次执行,这组任务是动态的,...

  • 一次性能调优总结

    批量任务和异步任务,批量任务采用分发方式,批量任务生产异步任务。总的情况是批量任务的生产速度大于异步任务的消耗速度...

  • CompletionService 源码解析

    CompletionService的主要作用是:按照异步任务的完成顺序,逐个获取到已经完成的异步任务。主要实现是在...

  • laravel 使用 job 和 event

    job 是异步执行。适用于长时间执行任务,-> 适合耗时长的任务。例如,批量发送邮件,短信。- 关注重点是正在处理...

  • 8. nextTick原理

    nextTick 原理 让一批方法异步的批量处理 原理:将异步需要执行的fn放到数组中,在微任务或宏任务里统一遍历...

  • 并发包之CompletionService

    CompletionService简介 将生产新的异步任务与使用已完成任务的结果分离开来的服务。生产者 submi...

  • Java并发编程 - CompletionService

    CompletionService接口的API文档说明如下: 将生产新的异步任务与使用已完成任务的结果分离开来的服...

  • 【javaScript练习】2021-02-23

    javaScript 作用域,异步执行,requestAnimationFrame 微任务,宏任务,异步执行 Ar...

网友评论

      本文标题:CompletionService批量执行异步任务

      本文链接:https://www.haomeiwen.com/subject/sfmiuctx.html