首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >专栏 >Java 并发编程·CompletableFuture

Java 并发编程·CompletableFuture

作者头像
数媒派
发布于 2022-12-01 03:43:32
发布于 2022-12-01 03:43:32
36300
代码可运行
举报
文章被收录于专栏:产品优化产品优化
运行总次数:0
代码可运行

CompletableFuture

Java 8 开始引入了 CompletableFuture,它针对 Future 做了改进,可以传入回调对象,当异步任务完成或者发生异常时,自动调用回调对象的回调方法。

CompletableFuture 的优点是:

  • 异步任务结束时,会自动回调某个对象的方法;
  • 异步任务出错时,会自动回调某个对象的方法;
  • 主线程设置好回调后,不再关心异步任务的执行。
代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
public class T {

    public static void main(String[] args) throws Exception {
        // 创建异步执行任务:
        CompletableFuture<Double> cf = CompletableFuture.supplyAsync(T::fetchPrice);
        // 如果执行成功:
        cf.thenAccept((result) -> {
            System.out.println("price: " + result);
        });
        // 如果执行异常:
        cf.exceptionally((e) -> {
            e.printStackTrace();
            return null;
        });
        // 主线程不要立刻结束,否则CompletableFuture默认使用的线程池会立刻关闭:
        Thread.sleep(2000);
    }

    static Double fetchPrice() {
        try {
            Thread.sleep(1000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        if (Math.random() < 0.3) {
            throw new RuntimeException("fetch price failed!");
        }
        return 5 + Math.random() * 20;
    }
}

除了实现了异步回调机制外,多个 CompletableFuture 可以串行执行。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
public class T {

    public static void main(String[] args) throws Exception {
        // 第一个任务:
        CompletableFuture<String> cfQuery = CompletableFuture.supplyAsync(() -> {
            return queryCode("中国石油");
        });
        // cfQuery成功后继续执行下一个任务:
        CompletableFuture<Double> cfFetch = cfQuery.thenApplyAsync(T::fetchPrice);
        // cfFetch成功后打印结果:
        cfFetch.thenAccept((result) -> {
            System.out.println("price: " + result);
        });
        // 主线程不要立刻结束,否则CompletableFuture默认使用的线程池会立刻关闭:
        Thread.sleep(2000);
    }

    static String queryCode(String name) {
        try {
            Thread.sleep(500);
        } catch (InterruptedException e) {
        }
        return "601857";
    }

    static Double fetchPrice(String code) {
        try {
            Thread.sleep(500);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        return 5 + Math.random() * 20;
    }
}

除了串行执行外,多个 CompletableFuture 还可以并行执行。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
public class T {

    public static void main(String[] args) throws Exception {
        // 两个CompletableFuture执行异步查询:
        CompletableFuture<String> cfQueryFromSina = CompletableFuture.supplyAsync(() -> {
            return queryCode("中国石油", "https://finance.sina.com.cn/code/");
        });
        CompletableFuture<String> cfQueryFrom163 = CompletableFuture.supplyAsync(() -> {
            return queryCode("中国石油", "https://money.163.com/code/");
        });

        // 用anyOf合并为一个新的CompletableFuture:
        CompletableFuture<Object> cfQuery = CompletableFuture.anyOf(cfQueryFromSina, cfQueryFrom163);

        // 两个CompletableFuture执行异步查询:
        CompletableFuture<Double> cfFetchFromSina = cfQuery.thenApplyAsync((code) -> {
            return fetchPrice((String) code, "https://finance.sina.com.cn/price/");
        });
        CompletableFuture<Double> cfFetchFrom163 = cfQuery.thenApplyAsync((code) -> {
            return fetchPrice((String) code, "https://money.163.com/price/");
        });

        // 用anyOf合并为一个新的CompletableFuture:
        CompletableFuture<Object> cfFetch = CompletableFuture.anyOf(cfFetchFromSina, cfFetchFrom163);

        // 最终结果:
        cfFetch.thenAccept((result) -> {
            System.out.println("price: " + result);
        });
        // 主线程不要立刻结束,否则CompletableFuture默认使用的线程池会立刻关闭:
        Thread.sleep(2000);
    }

    static String queryCode(String name, String url) {
        System.out.println("query code from " + url + "...");
        try {
            Thread.sleep((long) (Math.random() * 1000));
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        return "601857";
    }

    static Double fetchPrice(String code, String url) {
        System.out.println("query price from " + url + "...");
        try {
            Thread.sleep((long) (Math.random() * 1000));
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        return 5 + Math.random() * 20;
    }

}
本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
暂无评论
推荐阅读
编辑精选文章
换一批
2022-06-10:薯队长从北向南穿过一片红薯地(南北长M,东西宽N),红薯地被划分为1x1的方格,他可以从北边的任何一个格子
2022-06-10:薯队长从北向南穿过一片红薯地(南北长M,东西宽N),红薯地被划分为1x1的方格,
福大大架构师每日一题
2023/06/08
1450
2022-06-10:薯队长从北向南穿过一片红薯地(南北长M,东西宽N),红薯地被划分为1x1的方格,他可以从北边的任何一个格子
2022-04-20:小团去参加军训,军训快要结束了, 长官想要把大家一排n个人分成m组,然后让每组分别去参加阅兵仪式, 只能选择相邻的人一组,不能随意改变队伍
2022-04-20:小团去参加军训,军训快要结束了, 长官想要把大家一排n个人分成m组,然后让每组分别去参加阅兵仪式, 只能选择相邻的人一组,不能随意改变队伍中人的位置, 阅兵仪式上会进行打分,其中有一个奇怪的扣分点是每组的最大差值, 即每组最大值减去最小值, 长官想要让这分成的m组总扣分量最小,即这m组分别的极差之和最小。 长官正在思索如何安排中,就让小团来帮帮他吧。 答案2022-04-20: 动态规划。 时间复杂度:O(M N N)。 代码用rust编写。代码如下: use rand::Rng;
福大大架构师每日一题
2022/04/20
1910
2022-05-25:最大子段和是 一个经典问题,即对于一个数组找出其和最大的子数组。 现在允许你在求解该问题之前翻转这个数組的连续一段, 如翻转(1,2,3,
如翻转(1,2,3,4,5,6)的第三个到第五个元素組成的子数组得到的是(1,2,5,4,3,6),
福大大架构师每日一题
2022/05/25
4620
2022-05-25:最大子段和是 一个经典问题,即对于一个数组找出其和最大的子数组。 现在允许你在求解该问题之前翻转这个数組的连续一段, 如翻转(1,2,3,
2022-06-04:给定一个数字n,表示一开始有编号1~n的树木,列成一条直线, 给定一个有序数组arr,表示现在哪些树已经没了,arr[i]一定在[1,n]
2022-06-04:给定一个数字n,表示一开始有编号1~n的树木,列成一条直线,
福大大架构师每日一题
2022/06/05
2180
2022-06-04:给定一个数字n,表示一开始有编号1~n的树木,列成一条直线, 给定一个有序数组arr,表示现在哪些树已经没了,arr[i]一定在[1,n]
2022-06-04:给定一个数字n,表示一开始有编号1~n的树木,列成一条直线,给定一个有序数组arr,表示现在哪些树已经没了
2022-06-04:给定一个数字n,表示一开始有编号1~n的树木,列成一条直线,
福大大架构师每日一题
2023/06/08
1460
2022-06-04:给定一个数字n,表示一开始有编号1~n的树木,列成一条直线,给定一个有序数组arr,表示现在哪些树已经没了
2022-05-23:给定一个数组arr,你可以随意挑选其中的数字, 但是你挑选的数中,任何两个数a和b,必须Math.abs(a - b) > 1。 返回你最
let n: i32 = rand::thread_rng().gen_range(0, len) + 1;
福大大架构师每日一题
2022/05/23
5450
2022-05-23:给定一个数组arr,你可以随意挑选其中的数字, 但是你挑选的数中,任何两个数a和b,必须Math.abs(a - b) > 1。 返回你最
2022-04-14:小美有一个长度为n的数组, 为了使得这个数组的和尽量大,她向会魔法的小团进行求助。 小团可以选择数组中至多两个不相交的子数组, 并将区间里的数全都变为原来的10倍。 小团想知道他的魔法最多可以帮助小美将数组的和变大到多少?
2022-04-14:小美有一个长度为n的数组, 为了使得这个数组的和尽量大,她向会魔法的小团进行求助。 小团可以选择数组中至多两个不相交的子数组, 并将区间里的数全都变为原来的10倍。 小团想知道他
福大大架构师每日一题
2022/04/14
1.7K0
2023-03-02:给定一个数组arr,长度为n, 任意相邻的两个数里面至少要有一个被选出来,组成子序列,才是合法的! 求所有可能的合法子序列中,最大中位数是
2023-03-02:给定一个数组arr,长度为n,任意相邻的两个数里面至少要有一个被选出来,组成子序列,才是合法的!求所有可能的合法子序列中,最大中位数是多少?中位数的定义为上中位数,1, 2, 3, 4的上中位数是2,1, 2, 3, 4, 5的上中位数是3,2 <= n <= 10^5,1 <= arri <= 10^9。来自京东。实习岗位笔试题。答案2023-03-02:这道题看起来是实习题,实际上有难度。方法一:要i还是不要i,递归或者动态规划。方法二:以结果为导向,二分法。时间复杂度:O(N*
福大大架构师每日一题
2023/03/02
5960
2023-03-02:给定一个数组arr,长度为n, 任意相邻的两个数里面至少要有一个被选出来,组成子序列,才是合法的! 求所有可能的合法子序列中,最大中位数是
2022-09-11:arr是一个可能包含重复元素的整数数组,我们将这个数组分割成几个“块”, 并将这些块分别进行排序。之后再连接起来,使得连接的结果和按升序排
2022-09-11:arr是一个可能包含重复元素的整数数组,我们将这个数组分割成几个“块”,
福大大架构师每日一题
2022/09/11
6250
2022-09-11:arr是一个可能包含重复元素的整数数组,我们将这个数组分割成几个“块”, 并将这些块分别进行排序。之后再连接起来,使得连接的结果和按升序排
2022-05-10:在字节跳动,大家都使用飞书的日历功能进行会议室的预订,遇到会议高峰时期, 会议室就可能不够用,现在请你实现一个算法,判断预订会议时是否有空
2022-05-10:在字节跳动,大家都使用飞书的日历功能进行会议室的预订,遇到会议高峰时期,
福大大架构师每日一题
2022/05/10
5180
2022-05-02:给定一个数组arr,一个正数num,一个正数k, 可以把arr中的某些数字拿出来组成一组,要求该组中的最大值减去最小值<=num, 且该组
2022-05-02:给定一个数组arr,一个正数num,一个正数k, 可以把arr中的某些数字拿出来组成一组,要求该组中的最大值减去最小值<=num, 且该组数字的个数一定要正好等于k, 每个数字只能选择进某一组,不能进多个组。 返回arr中最多有多少组。 来自微软。 答案2022-05-02: 排序+动态规划。滑动窗口有陷阱,不一定行,可能可以。 第一种情况,包含i,dpi跟dpi-k相关。 第二种情况,不包含i,dpi=dpi-1。 时间复杂度O(N * logN)。 代码用rust编写。代码如下:
福大大架构师每日一题
2022/05/02
1K0
2022-04-15:给定一个非负数组arr,学生依次坐在0~N-1位置,每个值表示学生的安静值, 如果在i位置安置插班生,那么i位置的安静值变成0,同时任何同
2022-04-15:给定一个非负数组arr,学生依次坐在0~N-1位置,每个值表示学生的安静值,
福大大架构师每日一题
2022/04/15
4020
2022-12-06:定义一个概念叫“变序最大和“ “变序最大和“是说一个数组中,每个值都可以减小或者不变, 在必须把整体变成严格升序的情况下,得到的最大累加和
2022-12-06:定义一个概念叫"变序最大和" "变序最大和"是说一个数组中,每个值都可以减小或者不变, 在必须把整体变成严格升序的情况下,得到的最大累加和 比如,1,100,7变成1,6,7时,就有变序最大和为14 比如,5,4,9变成3,4,9时,就有变序最大和为16 比如,1,4,2变成0,1,2时,就有变序最大和为3 给定一个数组arr,其中所有的数字都是>=0的。 求arr所有子数组的变序最大和中,最大的那个并返回。 1 <= arr长度 <= 10^6, 0 <= arri <= 10^6。
福大大架构师每日一题
2022/12/06
6930
2022-12-06:定义一个概念叫“变序最大和“ “变序最大和“是说一个数组中,每个值都可以减小或者不变, 在必须把整体变成严格升序的情况下,得到的最大累加和
2022-06-23:给定一个非负数组,任意选择数字,使累加和最大且为7的倍数,返回最大累加和。 n比较大,10的5次方。 来自美团。3.26笔试。
2022-06-23:给定一个非负数组,任意选择数字,使累加和最大且为7的倍数,返回最大累加和。
福大大架构师每日一题
2022/06/23
3340
2022-06-23:给定一个非负数组,任意选择数字,使累加和最大且为7的倍数,返回最大累加和。 n比较大,10的5次方。 来自美团。3.26笔试。
2022-08-06:给定一个数组arr,长度为N,arr中所有的值都在1~K范围上, 你可以删除数字,目的是让arr的最长递增子序列长度小于K。 返回至少删除
2022-08-06:给定一个数组arr,长度为N,arr中所有的值都在1~K范围上,
福大大架构师每日一题
2022/08/06
1K0
2022-08-06:给定一个数组arr,长度为N,arr中所有的值都在1~K范围上, 你可以删除数字,目的是让arr的最长递增子序列长度小于K。 返回至少删除
2022-07-05:给定一个数组,想随时查询任何范围上的最大值。 如果只是根据初始数组建立、并且以后没有修改, 那么RMQ方法比线段树方法好实现,时间复杂度O
那么RMQ方法比线段树方法好实现,时间复杂度O(NlogN),额外空间复杂度O(NlogN)。
福大大架构师每日一题
2022/07/05
5610
2022-07-05:给定一个数组,想随时查询任何范围上的最大值。 如果只是根据初始数组建立、并且以后没有修改, 那么RMQ方法比线段树方法好实现,时间复杂度O
2022-08-22:给定一个数组arr,长度为n,最多可以删除一个连续子数组, 求剩下的数组,严格连续递增的子数组最大长度。 n <= 10^6。 来自字节。
2022-08-22:给定一个数组arr,长度为n,最多可以删除一个连续子数组,求剩下的数组,严格连续递增的子数组最大长度。n <= 10^6。来自字节。5.6笔试。答案2022-08-22:动态规划+线段树。代码用rust编写。代码如下:use rand::Rng;fn main() { let n: i32 = 100; let v: i32 = 20; let test_time: i32 = 50000; println!("测试开始"); for _ in 0..te
福大大架构师每日一题
2022/08/22
5870
2022-08-22:给定一个数组arr,长度为n,最多可以删除一个连续子数组, 求剩下的数组,严格连续递增的子数组最大长度。 n <= 10^6。 来自字节。
2022-05-07:返回一个数组中,所有降序三元组的数量。
2022-05-07:返回一个数组中,所有降序三元组的数量。 比如 : {5, 3, 4, 2, 1}, 所有降序三元组为 : {5, 3, 2}、{5, 3, 1}、{5, 4, 2}、{5, 4, 1}、 {5, 2, 1}、{3, 2, 1}、{4, 2, 1}。 所以返回数量7。 答案2022-05-07: 利用index tree。 时间复杂度:O(N * logN)。 空间复杂度:O(N)。 代码用rust编写。代码如下: fn main() { let mut arr: Vec<is
福大大架构师每日一题
2022/05/07
7440
2022-04-17:给定一个数组arr,其中的值有可能正、负、0, 给定一个正数k。 返回累加和>=k的所有子数组中,最短的子数组长度。 来自字节跳动。力扣8
2022-04-17:给定一个数组arr,其中的值有可能正、负、0, 给定一个正数k。 返回累加和>=k的所有子数组中,最短的子数组长度。 来自字节跳动。力扣862。 答案2022-04-17: 看到子数组,联想到结尾怎么样,开头怎么样。 预处理前缀和,单调栈。 达标的前缀和,哪一个离k最近? 单调栈+二分。复杂度是O(N*logN)。 双端队列。 时间复杂度:O(N)。 代码用rust编写。代码如下: fn main() { let arr: Vec<isize> = vec![2, -1, 2]
福大大架构师每日一题
2022/04/17
1.6K0
2022-06-08:找到非负数组中拥有“最大或的结果“的最短子数组,返回最短长度。
2022-06-08:找到非负数组中拥有"最大或的结果"的最短子数组,返回最短长度。
福大大架构师每日一题
2022/06/08
1.3K0
2022-06-08:找到非负数组中拥有“最大或的结果“的最短子数组,返回最短长度。
推荐阅读
2022-06-10:薯队长从北向南穿过一片红薯地(南北长M,东西宽N),红薯地被划分为1x1的方格,他可以从北边的任何一个格子
1450
2022-04-20:小团去参加军训,军训快要结束了, 长官想要把大家一排n个人分成m组,然后让每组分别去参加阅兵仪式, 只能选择相邻的人一组,不能随意改变队伍
1910
2022-05-25:最大子段和是 一个经典问题,即对于一个数组找出其和最大的子数组。 现在允许你在求解该问题之前翻转这个数組的连续一段, 如翻转(1,2,3,
4620
2022-06-04:给定一个数字n,表示一开始有编号1~n的树木,列成一条直线, 给定一个有序数组arr,表示现在哪些树已经没了,arr[i]一定在[1,n]
2180
2022-06-04:给定一个数字n,表示一开始有编号1~n的树木,列成一条直线,给定一个有序数组arr,表示现在哪些树已经没了
1460
2022-05-23:给定一个数组arr,你可以随意挑选其中的数字, 但是你挑选的数中,任何两个数a和b,必须Math.abs(a - b) > 1。 返回你最
5450
2022-04-14:小美有一个长度为n的数组, 为了使得这个数组的和尽量大,她向会魔法的小团进行求助。 小团可以选择数组中至多两个不相交的子数组, 并将区间里的数全都变为原来的10倍。 小团想知道他的魔法最多可以帮助小美将数组的和变大到多少?
1.7K0
2023-03-02:给定一个数组arr,长度为n, 任意相邻的两个数里面至少要有一个被选出来,组成子序列,才是合法的! 求所有可能的合法子序列中,最大中位数是
5960
2022-09-11:arr是一个可能包含重复元素的整数数组,我们将这个数组分割成几个“块”, 并将这些块分别进行排序。之后再连接起来,使得连接的结果和按升序排
6250
2022-05-10:在字节跳动,大家都使用飞书的日历功能进行会议室的预订,遇到会议高峰时期, 会议室就可能不够用,现在请你实现一个算法,判断预订会议时是否有空
5180
2022-05-02:给定一个数组arr,一个正数num,一个正数k, 可以把arr中的某些数字拿出来组成一组,要求该组中的最大值减去最小值<=num, 且该组
1K0
2022-04-15:给定一个非负数组arr,学生依次坐在0~N-1位置,每个值表示学生的安静值, 如果在i位置安置插班生,那么i位置的安静值变成0,同时任何同
4020
2022-12-06:定义一个概念叫“变序最大和“ “变序最大和“是说一个数组中,每个值都可以减小或者不变, 在必须把整体变成严格升序的情况下,得到的最大累加和
6930
2022-06-23:给定一个非负数组,任意选择数字,使累加和最大且为7的倍数,返回最大累加和。 n比较大,10的5次方。 来自美团。3.26笔试。
3340
2022-08-06:给定一个数组arr,长度为N,arr中所有的值都在1~K范围上, 你可以删除数字,目的是让arr的最长递增子序列长度小于K。 返回至少删除
1K0
2022-07-05:给定一个数组,想随时查询任何范围上的最大值。 如果只是根据初始数组建立、并且以后没有修改, 那么RMQ方法比线段树方法好实现,时间复杂度O
5610
2022-08-22:给定一个数组arr,长度为n,最多可以删除一个连续子数组, 求剩下的数组,严格连续递增的子数组最大长度。 n <= 10^6。 来自字节。
5870
2022-05-07:返回一个数组中,所有降序三元组的数量。
7440
2022-04-17:给定一个数组arr,其中的值有可能正、负、0, 给定一个正数k。 返回累加和>=k的所有子数组中,最短的子数组长度。 来自字节跳动。力扣8
1.6K0
2022-06-08:找到非负数组中拥有“最大或的结果“的最短子数组,返回最短长度。
1.3K0
相关推荐
2022-06-10:薯队长从北向南穿过一片红薯地(南北长M,东西宽N),红薯地被划分为1x1的方格,他可以从北边的任何一个格子
更多 >
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档
本文部分代码块支持一键运行,欢迎体验
本文部分代码块支持一键运行,欢迎体验