并发编程-08 Future&CompletableFuture用法

CompleteFuture的介绍和使用 阅读详情

Future&CompletableFuture使用详解

1、Future

1.1 Callable和Runnable的区别
  • Callable有返回值,Runnable无返回值
  • Callable可以抛出异常,Runnable无法抛出异常
@FunctionalInterface
public interface Runnable {
	//执行run方法,无返回值
    public abstract void run();
}

@FunctionalInterface
public interface Callable<V> {
    //计算出结果,或者在无法完成时抛出异常(有返回值V)
    V call() throws Exception;
}
1.2 Future
1.2.1 Future的方法
public interface Future<V> {
    //尝试中断线程任务,如果任务已完成该接口调用将返回false,执行中或未开始的任务中断或不在运行
    boolean cancel(boolean mayInterruptIfRunning);

    //任务完成前被取消则返回ture
    boolean isCancelled();

    //判断任务是否已完成
    boolean isDone();

    //阻塞等待任务结果
    V get() throws InterruptedException, ExecutionException;

	//阻塞等待任务结果,超时timeout则抛出异常
    V get(long timeout, TimeUnit unit)
        throws InterruptedException, ExecutionException, TimeoutException;
}
1.2.2 Future的常规用法

JDK源码中,Doug Lea提供了2种标准的Future用法

 interface ArchiveSearcher { String search(String target); }
 class App {
   ExecutorService executor = ...//线程池
   ArchiveSearcher searcher = ...//
   void showSearch(final String target) throws InterruptedException {
     Future<String> future = executor.submit(new Callable<String>() {
         @Override
         public String call() {
             return searcher.search(target);
         }});
     displayOtherThings(); // do other things while searching
     try {
       displayText(future.get()); // use future 阻塞获取即如果
     } catch (ExecutionException ex) { cleanup(); return; }
   }
 }

通过FutureTask创建任务future,交给线程池执行

  FutureTask<String> future =
   new FutureTask<String>(new Callable<String>() {
     public String call() {
       return searcher.search(target);
   }});
 executor.execute(future);
1.3 FutureTask

在这里插入图片描述

1.3.1 FutureTask的使用方法
  • FutureTask实现了Runnable和Future,既可以通过Runnable的方式执行,也可以通过Callable的方式获取结果。
  • FutureTask可以作为消费者和生产者的桥梁。由生产者提交任务,消费者等待future的结果(future.get())
public class FutureUseMyDemo {

    static ExecutorService executorService = Executors.newFixedThreadPool(3);
    public static void main(String[] args) {
        FutureTask futureTask1 = new FutureTask(new T1Task("飞刀"));
        FutureTask futureTask2 = new FutureTask(new T2Task());
        FutureTask futureTask3 = new FutureTask(new T3Task());
        executorService.submit(futureTask1);
        executorService.submit(futureTask2);
        executorService.submit(futureTask3);
        try {
            System.out.println(futureTask1.get());
            System.out.println(futureTask2.get());
            System.out.println(futureTask3.get());
        } catch (Exception e) {
            e.printStackTrace();
        }
        executorService.shutdown();
    }
    static class T1Task implements Callable<String> {
        private String extraName;
        public T1Task(String plusName){
            this.extraName = plusName;
        }

        @Override
        public String call() throws Exception {
            TimeUnit.SECONDS.sleep(2);
            return "小李"+extraName;
        }
    }

    static class T2Task implements Callable<String>{
        @Override
        public String call() throws Exception {
            TimeUnit.SECONDS.sleep(3);
            return "张三";
        }
    }

    static class T3Task implements Callable<String>{
        @Override
        public String call() throws Exception {
            TimeUnit.SECONDS.sleep(5);
            return "王五";
        }
    }
}
1.3.2 FutureTask使用注意事项
  • 当 for 循环批量获取 Future#get()容易 block时,可以使用get(timeout)保证不产生死锁
  • Future 的生命周期不能后退
1.3.3 FutureTask的局限性
  • 并发执行多任务时,get()结果时线程只能等待
  • 无法对多个任务执行链式调用,A任务结束之后开始执行B任务
  • 无法组合多个任务,Future无法保证在运行多个任务全部执行结束后执行特定动作
  • 没有关于异常的处理方法

2、CompletionService

在这里插入图片描述

2.1 CompletionService的原理和优点
  • 内部通过阻塞队列+FutureTask,实现了任务先完成先获取结果,按顺序获取排序排序。
  • 内部有先进先出的阻塞队列,用于保存已经执行完成的Future
  • take()或poll()方法,拿到已完成的Future
  • Future#get()接口获取最终结果
2.2 应用场景
2.2.1 常用方式
public class CompletionServiceDemo {

    public static void main(String[] args) throws InterruptedException, ExecutionException {

        //创建线程池
        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++) {
            //从阻塞队列获取futureTask
            Integer r = cs.take().get();
            executor.execute(() -> save(r));
        }


        executor.shutdown();
    }

    private static void save(Integer r) {
        log.debug("保存询价结果:{}",r);
    }

    private static Integer getPriceByS1() throws InterruptedException {
        TimeUnit.MILLISECONDS.sleep(5000);
        log.debug("电商S1询价信息1200");
        return 1200;
    }
    private static Integer getPriceByS2() throws InterruptedException {
        TimeUnit.MILLISECONDS.sleep(8000);
        log.debug("电商S2询价信息1000");
        return 1000;
    }
    private static Integer getPriceByS3()  throws InterruptedException {
        TimeUnit.MILLISECONDS.sleep(3000);
        log.debug("电商S3询价信息800");
        return 800;
    }
}
2.2.2 Dubbo Forking集群模式,单个任务成功时就返回
public class CompletionServiceDemo2 {
    public static void main(String[] args){
        Instant now = Instant.now();
        Object address = geocoder("address");
        System.out.println(Duration.between(now, Instant.now()));
    }

    @SneakyThrows
    public static Object geocoder(String addr){
        //创建线程池
        ExecutorService executor = Executors.newFixedThreadPool(10);
        //创建CompletionService
        CompletionService<Boolean> cs = new ExecutorCompletionService<>(executor);
        //并行执行3个查询任务,当有1个任务获取结果后,则return
        cs.submit(() -> geocoderByS1(addr));
        cs.submit(() -> geocoderByS2(addr));
        cs.submit(() -> geocoderByS3(addr));
        Instant now = Instant.now();
/*        for (int i = 0; i < 3; i++) {
			//此处可以看到take()方法也是阻塞式的
            System.out.println(cs.take().get());
            System.out.println(Duration.between(now, Instant.now()));
        }*/
        return cs.take().get();
    }
    @SneakyThrows
    public static Boolean geocoderByS1(String addr) {
        TimeUnit.SECONDS.sleep(5);
        return true;
    }

    @SneakyThrows
    public static Boolean geocoderByS2(String addr) {
        TimeUnit.SECONDS.sleep(8);
        return true;
    }

    @SneakyThrows
    public static Boolean geocoderByS3(String addr){
        TimeUnit.SECONDS.sleep(2);
        return true;
    }
}

#PrintResult 
 PT2.054S
  • 批量提交异步任务时,可以使用CompletionService

  • CompletionService将线程池Executor和阻塞队列BlockingQueue的功能融合在了一

    起,能够让批量异步任务的管理更简单

  • CompletionService能够让异步任务的执行结果有序化。先执行完的先进入阻塞队列。

  • 线程池隔离。CompletionService支持自己创建线程池,这种隔离性能避免几个特别耗时的任务拖垮整个应用的风险。

3、CompletableFuture

3.1 CompletableFuture特点
  • CompletableFuture支持业务逻辑处理存在串行[依赖]、并行、聚合的关系
  • CompletableFuture是Future接口的扩展和增强
  • CompletableFuture实现了对任务的编排能力
  • 默认线程池:ForkJoinPool.commonPool()
3.1 应用场景
  • 描述依赖关系:
    • thenApply() 把前面异步任务的结果,交给后面的Function
    • thenCompose()用来连接两个有依赖关系的任务,结果由第二个任务返回
  • 描述and聚合关系:
    • thenCombine:任务合并,有返回值
    • thenAccepetBoth:两个任务执行完成后,将结果交给thenAccepetBoth消耗,无返回值
    • runAfterBoth:两个任务都执行完成后,执行下一步操作(Runnable)。
  • 描述or聚合关系:
    • applyToEither:两个任务谁执行的快,就使用那一个结果,有返回值。
    • acceptEither: 两个任务谁执行的快,就消耗那一个结果,无返回值。
    • runAfterEither: 任意一个任务执行完成,进行下一步操作(Runnable)。
  • 并行执行:
    • CompletableFuture类自己也提供了anyOf()和allOf()用于支持多个CompletableFuture并行执行
3.2 常用方法总结
  • runAsync 方法以Runnable函数式接口类型为参数,没有返回结果,
  • supplyAsync 方法Supplier函数式接口类型为参数,返回结果类型为U;Supplier 接口的 get() 方法是有返回值的(会阻塞)
  • join()和get()方法都是用来获取CompletableFuture异步之后的返回值,join()方法抛出的是uncheck异常,get()方法抛出的是经过检查的异常,ExecutionException, InterruptedException 需要用户手动处理
3.3 使用案例
public static void main(String[] args) throws ExecutionException, InterruptedException {

    Runnable runnable = () -> System.out.println("执行无返回结果的异步任务");
    CompletableFuture.runAsync(runnable);

    CompletableFuture<String> future = CompletableFuture.supplyAsync(() -> {
        System.out.println("执行有返回值的异步任务");
        try {
            Thread.sleep(5000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        return "Hello World";
    });
    String result = future.join();
    System.out.println(result);
}
pletableFuture.supplyAsync(() -> {
        System.out.println("执行有返回值的异步任务");
        try {
            Thread.sleep(5000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        return "Hello World";
    });
    String result = future.join();
    System.out.println(result);
}
并发编程第一阶段 提示:并发编程给我们带来了什么作用可以加快响应用户的时间、使你的代码模块化,异步化,简单化、充分利用CPU的资源提示:以下是本篇文章正文内容,下面案例可供参考Future和FutureTask可以和Callable配合使用Callable的Call方法有返回值,可以声明抛出异常Future对具体的Runnable或者Callable任务的执行结果进行取消、查询是否完成、获取结果。必要时通过get方法阻塞任务返回结果。Future实际采用FutureTask实现。 阅读详情

相关推荐

InVEST模型实战指南:从水源涵养到热岛缓解的生态系统服务评估

本文提供了InVEST模型的实战指南,详细介绍了从环境搭建、数据预处理到核心模型应用的完整流程。通过水源涵养、碳存储、土壤保持和城市热岛缓解等核心模型的拆解,帮助生态学者与规划者系统量化评估生态系统服务,将复杂的生态价值转化为直观的空间数据与地图,为科学决策提供有力支撑。

weixin_29197051的博客 429

Future、CompletableFuture概述

Future、CompletableFuture概述

y516369的博客 2878

低功耗模式下的看门狗使用

最近用国产芯片AT32在做一个低功耗的项目,为了实现低功耗模式下的定时唤醒,我选择的是使用相对比较简单的看门狗来做,下面就分享一下使用过程~ 为了最大限度的降低功耗,我用的是待机模式,先看看几种低功耗模式以及唤醒的区别: 而看门狗AT32提供了两种,分别是独立看门狗(IWDG)和窗口看门狗(WWDG),其区别大概有以下几点: 1、独立看门狗(IWDG)由专用的低速时钟(LSI)驱动,即使主时钟发生故障它也仍然有效;窗口看门狗由从 APB1 时钟分频后得到的时钟驱动,通过可配置的时间窗口来检测应用程序非正常

dc18883988396的博客 3028

Future与CompletableFuture

Future与CompletableFuture的比较与使用

任天柳 1435

Proxmox VE 9 更换源

创建一键更换Proxmox VE 9.0源的Bash脚本,实现快速替换软件源。脚本需包含订阅提醒关闭功能,兼容Proxmox VE 9.0系统,执行命令为bash /proxmox_9.0_Repo.sh。该工具可简化源配置过程,自动处理系统更新源替换及订阅提示屏蔽,适合需要快速配置Proxmox环境的用户使用。

极致,细节 4984

在 ABAP 平台上搭建 OAuth 2.0 Server:架构、流程、权限与落地实战

摘要:本文为SAP ABAP开发人员提供将ABAP平台配置为OAuth 2.0授权服务器的实战指南。重点介绍两种授权流程(授权码和SAML Bearer)的实现方案,包括核心事务配置(SOAUTH2/SAML2)、授权对象(S_SCOPE)管理以及端点交互规范。通过具体配置清单和三类典型集成场景(第三方Web应用访问OData、企业集成平台调用、BTP应用对接)的落地示例,帮助读者快速构建安全的OAuth 2.0服务架构。文档强调SSL/TLS基础安全、scope最小授权原则以及授权与令牌端点的标准交互模式

2007 年 ~ 2025 年,深耕 SAP 技术 18 年 308

深入理解Java并发:Future与CompletableFuture详解

在多线程编程中,异步计算是一种常见的需求。其中Future和CompletableFuture是处理异步计算结果的两大核心接口。本文将详细介绍Future和CompletableFuture的概念、使用方法以及它们之间的区别。Future为Java引入了异步计算的概念,而CompletableFuture在此基础上进行了全面升级,提供了更为强大和灵活的异步编程工具集。在进行高并发、高性能应用开发时,合理运用CompletableFuture能够显著提升系统的响应速度和资源利用率。

TFHoney的博客 3757

基于Qt的工业组态软件开发:图形绘制与TCP通讯实现

在数据接收时,通过 readyRead 信号触发解析函数,校验数据包完整性后提取有效数据,并更新对应图形元素的状态,例如根据温度值改变矩形的填充色,实现设备状态可视化。测试阶段,我们将软件部署到Windows工控机,连接PLC设备进行通讯测试,结果表明图形元素响应及时,TCP数据传输稳定,满足工业现场的基本需求。综上所述,基于Qt的组态软件开发,核心在于利用 QGraphicsView 框架实现图形元素的灵活绘制与管理,结合 QTcpSocket 完成工业数据的可靠交互。

谢谢大家的关注和点赞!这里只有纯纯的知识干货,没有一句废话。希望能实实在在帮到大家~要是觉得有用,别忘了给我点支持哟,你 272

Future和CompletableFuture详解

CompletableFuture有且只有一个构造方法,这个构造方法的注解表示创造一个新的不完整的CompletableFuture,所以当我们需要用到CompletableFuture的时候,不要用new来创建。Future接口(FutureTask实现类)定义了操作异步任务执行的一些方法,如获取异步任务执行结果、取消任务的执行、判断任务是否被取消、判断任务执行是否完毕等。如果想将多个异步任务的计算结果组合起来,后一个异步任务的计算结果需要前一个异步任务的值。对比串行执行,效率还是有很大的提升。

weixin_45948019的博客 940

材料力学数值方法:细观力学模拟:材料断裂与损伤的细观模拟_2024-08-05_16-13-13.Tex

弹性理论是材料力学的一个重要分支,主要研究在外部载荷作用下,材料如何发生弹性变形以及如何恢复原状。这一理论基于连续介质力学,将材料视为由无数连续点组成的连续体,每个点都遵循一定的力学规律。弹性理论的核心是胡克定律,它表明在弹性范围内,应力与应变成正比关系。损伤变量ddd通常定义为0到1之间的值,其中d0d=0d0表示材料未损伤,d1d=1d1表示材料完全损伤。损伤变量可以基于不同的物理量定义,如裂纹密度、孔隙率或微观缺陷的分布。

938

Spring AI Alibaba实战训练营-16 NL2SQL (自然语言转 SQL)应用开发指南

本文介绍了一个基于AI的智能BI应用开发项目,主要实现自然语言转SQL(NL2SQL)功能,包含对话模块、MCP模块、向量数据管理模块。项目采用Spring AI Alibaba框架,集成通义千问大模型,支持内存向量库和AnalyticDB向量数据库两种存储方案。重点展示了chat模块的三个控制器实现:AnalyticNl2SqlController用于生产环境,SimpleChatController适用于开发测试,Nl2sqlForGraphController支持基于图的复杂对话流程。系统通过将业务知

program哲学 1585

Future&CompletableFuture实战

直接继承Thread或者实现Runnable接口都可以创建线程,但是这两种方法都有一个问题就是:没有返回值,也就是不能获取执行完的结果。因此java1.5就提供了Callable接口来实现这一场景,而Future和FutureTask就可以和Callable接口配合起来使用。

Zhuxiaoyu_91的博客 1106

【并发编程学习篇】Future&CompletableFuture的使用与原理剖析

当需要批量提交异步任务的时候建议你使用CompletionServiceCompletionService将线程池Executor和阻塞队列BlockingQueue的功能融合在了一起,能够让批量异步任务的管理更简单。CompletionService能够让异步任务的执行结果「有序化」先执行完的先进入阻塞队列,利用这个特性,你可以轻松实现后续处理的有序性,避免无谓的等待,同时还可以快速实现诸如Forking Cluster这样的需求。线程池隔离。

一个勤勤恳恳的程序猿 7033

win10 跳过U8环境检测的IE WebControls.rar

win10 安装u8的时候 提示IE WebControls 不通过,这个工具可以欺骗u8的检查。 跳过U8环境检测的IE WebControls。提示导入失败后,重新检测通过。

C# WinForm 基于DirectShow.dll编写的程序,可边预览边保存视频,音频和图片

基于微软的DirectShow.dll的二次开发1.自动识别连接的摄像头跟麦克风且可以对其进行选择(默认选中第一个)2.可录制wmv和avi两种格式的视频并且都带有音频,avi可以录制的分辨率和帧数进行选择,wmv默认进行了淸晰度优化如不喜欢可去除代码中有相关提示3.可在预览点开之后进行拍照,也可边录制视频边拍照4.添加了视频和音频的压缩功能(酌情使用)这次二次开发发现C#对DirectShow的相关信息太少,这次做完也不敢藏私共享出来,还望大家指正

并发编程——02 异步编程Future&CompletableFuture实战

Callable&Future&FutureTask、CompletableFuture

念头通达 757

Probability and Statistics - 4th edition

Probability and Statistics - 4th edition

异步编程Future&CompletableFuture实战

本文深入解析Java异步编程中的Future和CompletableFuture核心用法。首先指出Future的局限性:阻塞式获取结果、无法链式调用、任务组合困难、异常处理缺失。随后重点讲解CompletableFuture的核心方法,包括异步任务创建(runAsync/supplyAsync)、结果处理(thenApply/thenCombine)、异常处理(exceptionally/whenComplete)以及任务组合(allOf/anyOf)。通过真实代码示例和面试题解析,帮助开发者掌握异步编程精

慢慢 960

Future&CompletableFuture

直接继承Thread或者实现Runnable接口都可以创建线程,但是这两种方法都有一个问题就是:没有返回值,也就是不能获取执行完的结果。因此java1.5就提供了Callable接口来实现这一场景,而Future和FutureTask就可以和Callable接口配合起来使用。

盲目的拾荒者的博客 255

2.Future&CompletableFuture

直接继承Thread或者实现Runnable接口都可以创建线程,但是这两种方法都有一个问题就是:没有返回值,也就是不能获取执行完的结果。因此java1.5就提供了Callable接口来实现这一场景,而Future和FutureTask就可以和Callable接口配合起来使用。

weixin_43164559的博客 1162

JUC-Future&CompletableFuture

thenApply方法中的函数返回一个值,这个值成为新的CompletableFuture的结果。,这个新实例的结果要么是原CompletableFuture的正常结果(如果原CompletableFuture正常完成),要么是通过fn函数处理异常后返回的值(如果原CompletableFuture因异常而失败)。thenCompose方法中的函数返回一个新的CompletableFuture,这个CompletableFuture的结果成为新的CompletableFuture的结果。

weixin_52717390的博客 1115

2-2-3-7、Future&CompletableFuture详解

当需要批量提交异步任务的时候建议你使用CompletionService。CompletionService将线程池Executor和阻塞队列BlockingQueue的功能融合在了一起,能够让批量异步任务的管理更简单CompletionService能够让异步任务的执行结果有序化。先执行完的先进入阻塞队列,利用这个特性,你可以轻松实现后续处理的有序性,避免无谓的等待,同时还可以快速实现诸如Forking Cluster这样的需求线程池隔离。

技术,就是不断的深入~ 1325

JUC学习笔记-12-Future&CompletableFuture学习

Future 1 Future的认识 Future表示一个可能还没有完成的异步任务的结果。 线程是属于异步计算模型,所以你不可能直接从别的线程中得到函数返回值。 这时候,Future就出场了。Futrue可以监视目标线程调用call的情况,当你调用Future的get()方法以获得结果时,当前线程就开始阻塞,直接call方法结束返回结果。 2 Future的体系结构图 Future接口定义了主要的5个接口方法,有RunnableFuture和SchedualFuture继承这个接口,以及CompleteFu

小小学渣的博客 444
上一篇: 并发编程-07 ForkJoin分治
下一篇: 服务化-mysql-07 实战分析mysql慢查询
旧梦昂志
博客等级 码龄7年 3724粉丝 68原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

旧梦昂志

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值