CompletionService的基本使用以及原理

news2024/12/24 3:14:35

文章目录

  • 一、CompletionService的简介
  • 二、CompletionService的底层大致原理
  • 三、CompletionService的使用场景
    • 1. 批量下载文件:
    • 2. 多个商品价格查询:
    • 3. 并发处理多个API请求:
  • 四、CompletionService的使用demo
    • 1. 代码如下:
    • 2. 案例分析:

一、CompletionService的简介

CompletionService

  1. CompletionService是Java并发编程中的一个工具类,它实现了一个任务完成的队列,并且可以按照任务完成的顺序来获取任务的结果。

  2. CompletionService的主要作用是提供一种方式来处理一批并发执行的任务,并且在它们完成后按照完成的顺序获取结果。它通常与ExecutorService一起使用。

  3. 使用CompletionService可以将一组任务提交给ExecutorService去执行,并且通过调用CompletionService的take()方法来获取已经完成的任务的结果。take()方法会阻塞直到有一个任务完成,并且返回一个Future对象,通过这个对象可以获取任务的结果。

  4. CompletionService的优势在于它可以提供任务完成的顺序,这对于需要按照任务完成的顺序来处理结果的场景非常有用。在处理一组任务时,如果只使用普通的ExecutorService,那么需要自己维护一个任务完成的队列,并且需要使用额外的同步机制来保证任务的顺序,而使用CompletionService可以简化这个过程。

  5. 总结起来,CompletionService是一个用于处理一组并发执行的任务,并按照任务完成的顺序获取结果的工具类。它可以简化任务结果的处理过程,并提供更方便的方式来获取已经完成的任务的结果。

二、CompletionService的底层大致原理

底层原理

  1. CompletionService的底层实现主要依赖于ExecutorCompletionService类,在这个类中,它内部维护了一个阻塞队列(BlockingQueue)和一个ExecutorService对象。

  2. 具体来说,ExecutorCompletionService的构造函数会接收一个ExecutorService对象,并使用它来执行任务。同时,它会创建一个LinkedBlockingQueue对象作为阻塞队列,用于存储已完成的任务的结果。

  3. 当任务提交给ExecutorService进行执行时,ExecutorCompletionService会将任务包装成一个FutureTask对象,并将其提交给ExecutorService。在任务执行完成后,ExecutorService会将结果添加到阻塞队列中。

  4. 在获取任务结果时,ExecutorCompletionService会调用阻塞队列的take()方法,该方法会阻塞直到队列中有任务结果可取。一旦有任务结果可取,take()方法将返回一个Future对象,通过这个对象可以获取任务的结果。

  5. 需要注意的是,ExecutorCompletionService内部使用了一个专门的类为已完成的任务结果进行包装,这个类叫做QueueingFuture。QueueingFuture继承自FutureTask,并添加了一个done()方法,用于在任务执行完成后将结果添加到阻塞队列中。

  6. 总结起来,CompletionService的底层原理是通过使用ExecutorCompletionService类,它内部维护了一个阻塞队列和一个ExecutorService对象。任务提交给ExecutorService进行执行后,结果会被包装成QueueingFuture对象,并添加到阻塞队列中。在获取任务结果时,通过调用阻塞队列的take()方法来获取已完成的任务结果。

三、CompletionService的使用场景

虽然CompletionService主要是用于并发编程和多线程任务处理,但也可以在某些生活场景中找到类似的应用。

1. 批量下载文件:

假设你要从多个网站上下载大量的文件,可以将每个下载任务提交给CompletionService,它将负责并发地下载文件并返回下载结果。这样可以提高下载的效率,并且可以在任何一个文件下载完成后立即处理它。

2. 多个商品价格查询:

假设你想要比较多个不同网站上的商品价格,可以将每个商品的价格查询任务提交给CompletionService。它可以并发地查询每个网站上的商品价格,并将结果返回给你。这样可以快速地获取多个网站上的价格信息。

3. 并发处理多个API请求:

如果你需要同时向多个API发送请求,并等待它们的响应,可以使用CompletionService。你可以将每个请求任务提交给CompletionService,它将负责并发地发送请求并返回响应结果。这样可以提高API请求的效率,并在任意一个请求完成后立即处理它。

四、CompletionService的使用demo

1. 代码如下:

以多个商品价格查询为例:

import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.*;

public class PriceComparison {
    public static void main(String[] args) {
        // 创建CompletionService
        ExecutorService executor = Executors.newFixedThreadPool(5);
        CompletionService<Double> completionService = new ExecutorCompletionService<>(executor);

        // 模拟多个商品的价格查询任务
        List<String> products = new ArrayList<>();
        products.add("product1");
        products.add("product2");
        products.add("product3");

        // 提交价格查询任务
        for (String product : products) {
            completionService.submit(() -> {
                // 模拟查询商品价格的逻辑,这里使用随机数模拟价格
                double price = Math.random() * 100;
                Thread.sleep((long) (Math.random() * 1000)); // 模拟查询时间
                return price;
            });
        }

        // 获取查询结果
        for (int i = 0; i < products.size(); i++) {
            try {
                Future<Double> result = completionService.take();
                Double price = result.get();
                System.out.println("Product " + products.get(i) + " price: $" + price);
            } catch (InterruptedException | ExecutionException e) {
                e.printStackTrace();
            }
        }

        // 关闭ExecutorService
        executor.shutdown();
    }
}

2. 案例分析:

  1. 在上述代码中,我们使用CompletionService实现了并发地查询多个商品的价格。首先,我们创建了一个ExecutorService,用于执行查询任务。然后,我们将每个商品的价格查询任务提交给CompletionService,它会负责并发地查询每个网站上的商品价格,并将结果返回给我们。最后,我们通过调用completionService.take()方法来获取查询结果,这个方法会阻塞直到有任务完成并返回结果。在获取到结果后,我们可以进行相应的处理。

  2. 通过使用CompletionService,我们可以并发地查询多个网站上的商品价格,并且能够快速地获取到所有网站上的价格信息。这样可以提高价格比较的效率,并且能够及时获取到所有网站上的最新价格。同时,我们还可以通过调整线程池的大小来控制并发查询的程度,从而进一步优化性能。

  3. 总结起来,CompletionService是一个非常有用的工具,可以在并发编程中方便地处理多个任务并获取结果。它适用于各种场景,包括生活中的实际应用。通过合理地利用CompletionService,我们可以提高任务处理的效率,并且能够更好地利用多线程和并发编程的优势。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/747497.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

mac上 如何批量在文件名中插入文字

mac上 如何批量在文件名中插入文字&#xff1f;在使用Mac电脑的时候&#xff0c;我们经常需要对大量文件的名称进行修改&#xff0c;例如需要在大量文件的名称中插入一些相同的文字或者字符的时候&#xff0c;你会用什么方法来完成这项工作呢&#xff1f;相信很多人就面对过类似…

前端vue入门(纯代码)30_路由的props配置

喜欢的东西太贵了&#xff0c;我一咬牙&#xff0c;狠下心决定不喜欢了&#xff01; 【28.Vue Router--路由的props配置】 props配置官网文档 props属性用法和params属性差不多&#xff0c;都是要在src/router/index.js文件中配置 // 该文件专门用于创建整个应用的路由器 i…

Spring 项目的创建和使用1(配置国内源)

目录 一、Spring项目的创建 1. 创建Maven项目 2. 添加Spring依赖&#xff08;重要&#xff09; (1) 必须要设置两个配置文件的国内源配置&#xff08;当前项目配置文件&#xff0c;新项目配置文件&#xff09; (2) 复制上一步中的User setting file 后面的路径在文件资源管理…

SpringBoot集成Flowable工作流

SpringBoot集成Flowable工作流 Flowable是什么&#xff1f;一、添加依赖二、flowable配置三、定义流程文件1.使用流程文件定义工作流2.idea使用插件来定义流程图1.安装插件2.创建bpmn文件并画流程图3.右击流程用模型设计器打开文件 四、测试controller Flowable是什么&#xff…

美女与修狗儿【 InsCode Stable Diffusion 美图活动一期】

女朋友最近买了一只小泰迪&#xff0c;于是给她和修狗儿做一幅画 一、Stable Diffusion 模型在线使用地址 https://inscode.csdn.net/inscode/Stable-Diffusion 二、模型版本及相关配置 模型&#xff1a;chilloutmix-Ni.safetensors[7234b76e42采样方法&#xff1a;Euler a…

算法拾遗三十五indexTree和AC自动机

算法拾遗三十五indexTree和AC自动机 indexTree&#xff08;树状数组&#xff09;indexTree规则 IndexTree二维AC自动机 indexTree&#xff08;树状数组&#xff09; 给定数组下标统一从1开始 如果要求L。。R范围上任意区间的和&#xff0c;我们通常的解法是定义一个help&…

msvcp140.dll重新安装的解决方法,msvcp140.dll丢失修复教程

计算提示msvcp140.dll丢失需要怎么重新安装呢&#xff1f;下面小编就把msvcp140.dll丢失重新安装的修复教程分享给大家。msvcp140.dll是Microsoft Visual C Redistributable文件的一部分&#xff0c;它是一个动态链接库文件。该文件包含了一些用于C程序开发的函数和类的定义&am…

【Vue2.0源码学习】模板编译篇-模板解析阶段(HTML解析器)

文章目录 1. 前言2. HTML解析器内部运行流程3. 如何解析不同的内容3.1 解析HTML注释3.2 解析条件注释3.3 解析DOCTYPE3.4 解析开始标签3.5 解析结束标签3.6 解析文本 4. 如何保证AST节点层级关系5. 回归源码5.1 HTML解析器源码5.2 parseEndTag函数源码 6. 总结 1. 前言 上篇文…

如何应对ChatGPT这一波AI浪潮

最近我在写一系列文章&#xff0c;其中包括《ChatGPT 实战系列》和《WPS Office AI实战系列》。想通过这些文章提供实践指导&#xff0c;既自己动手实践了&#xff0c;也能与大家分享我的实践结果&#xff0c;这是一个学习的过程。在实践过程中&#xff0c;我发现有些实用的方面…

基于springboot文学创作的社交论坛新闻文章系统vue

相比于传统的社交论坛管理方式&#xff0c;智能化的管理方式可以大幅提高社交论坛的管理效率&#xff0c;实现了社交论坛管理的标准化、制度化、程序化的管理&#xff0c;有效地防止了社交论坛信息的随意管理&#xff0c;提高了信息的处理速度和精确度&#xff0c;能够及时、准…

OnlyHome三代金属智能手环|健康、科技齐实现

近年来,人们越来越追求生活的品质与趣味,生活中的一点点小确幸、小惊喜最能让人感受到深深地愉悦。这不,Only&Home三代金属智能手环也带来了惊喜,有了它,健康、科技两手抓,享受生活更自由。 Only&Home三代金属智能手环给人的第一印象是它超高的颜值,延用了二代手环奢华…

Proton 推出开源密码管理器,兼身份管理器

导读Proton 是由来自欧洲核研究组织 (CERN) 的科学家于 2014 年在瑞士日内瓦创立的一家公司&#xff0c;其最知名的应该就是电子邮件服务 Proton Mail&#xff0c;主打端到端加密、安全和隐私保护。Proton 由科学家领导&#xff0c;其中包括万维网的发明者 Tim Berners-Lee。 …

高速入门知识02:降低串扰和维持信号完整性的布线方法

文章目录 前言一、单端走线布线1.1.带有短截线的菊花链布线1.2.没有短截线的菊花链布线1.3.星型布线1.4.蛇型布线 二、差分走线布线 前言 串扰是并行走线间不需要的信号耦合。微带线和带状线正确的布线和叠层布局能够降低串扰。 双带线布局有两个靠近的信号层&#xff0c;为降…

MQ的优劣势及RabbitMQ相关概念

一&#xff0c;MQ 1&#xff0c;MQ 的概念 MQ 全称 Message Queue&#xff08;消息队列&#xff09;&#xff0c;是用来存储消息数据的容器&#xff08;是一个中间件&#xff09;&#xff0c;一般用于分布式系统间的通信&#xff1b;MQ主要介于生产者和消费者之间&#xff0c…

lwip-2.1.3自带的httpd网页服务器使用教程(一)从SD卡读取网页文件并显示

概述 本教程使用的单片机是STM32F103ZE&#xff0c;有线网口芯片为ENC28J60。 本教程里面的网页由于需要兼容Windows XP系统的IE8浏览器&#xff0c;所以采用HTML 4.01编写&#xff0c;不使用任何前端框架。笔者使用的网页设计软件是Adobe Dreamweaver CS3。 开发板PCB文件是公…

推荐Selenium 自动化测试实战

你将获得 深入 Selenium 源码、原理、封装、技巧&#xff1b; unittest、pytest、DDT、POM 迭代测试方法&#xff1b; 大型项目分布式测试解决方案&#xff1b; Jenkins 持续集成和交付。 演示地址&#xff1a;www.runruncode.com/portal/article/index/id/19451/cid/85.html 课…

【无线通信专题】NFC基本原理

NFC定义 NFC(Near Field Communication)近场通信。 NFC早期应用 NFC最开始的应用主要用于金融领域,POS机(reader)通过非接触的方式与银行卡(带NFC接口的卡片)进行交互得到银行卡信息并完成支付。因为NFC的通信距离比较近,所以安全性较高。 后来随着手机支付的流行。…

使用STM32实现 蓝牙插座

硬件介绍 蓝牙模块HC-01&#xff0c;其实之前就用过&#xff0c;使用起来非常简单 继电器模块&#xff0c; (VCC 3.3V)当左侧IN输入低电平时&#xff0c;右侧的ON 和 COM会导通&#xff0c;左上的绿灯会亮&#xff0c;此处充当插座的角色 项目需求 通过蓝牙的串口发送open打开…

JMeter 中 3 种参数值的传递

目录 前言&#xff1a; (一) 从 CSV 文件读取要批量输入的变量 (二) 利用 Cookie 进行值的传递 (三) 利用正则匹配提取上一个接口的返回数据作为下个请求的输入 前言&#xff1a; 在JMeter中&#xff0c;参数值的传递是非常重要的&#xff0c;因为它允许你在测试过程中动态…

Spring 如何解决 Bean 的循环依赖(循环引用)

Component public class A {Autowiredprivate B b;}Component public class B {Autowiredprivate A a;}上面的情况就是 循环依赖 Bean的创建初始化过程如下 如果不采取措施&#xff0c;那么循环依赖就会进入死循环 但 Spring 已经帮我们解决了大部分循环依赖问题 具体是如何解…