CompletableFuture 简介和使用

前言:Futrue的缺点有(1)get方法会阻塞 ,(2)不支持注册回调方法 ,(3)不支持级联操作

CompletableFuture弥补了这些缺点

 

直接上代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
public class CompletableFutureTest {
 
    public static void main(String[] args) throws Exception {
 
//        test1();
//        test2();
//        test3();
          test4();
    }
 
 
    //采用了callable+ future方式  ,get方法获取任务的返回值会被阻塞住
    public  static  void  test1() throws  Exception {
        ExecutorService executor = Executors.newCachedThreadPool();
        Future<String> result = executor.submit(()->{
            //模拟执行耗时任务
            System.out.println("task doing...");
            try {
                Thread.sleep(3000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            //返回结果
            return "result";
        });
        //这里只是将空闲的线程中断,将线程池的状态改为shutdown,不能继续往线程池中添加任务
        executor.shutdown();
        System.out.println("task运行结果" + result.get());
    }
 
    //采用了competableFuture,采用回调的方式获取任务的返回值
    public static void test2() throws Exception {
        //supplyAsync内部使用ForkJoinPool线程池执行任务
        CompletableFuture<String> completableFuture=CompletableFuture.supplyAsync(()->{
            //模拟执行耗时任务
            System.out.println("task doing...");
            try {
                Thread.sleep(3000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            //返回结果
            return "100";
        }).whenComplete((v,r)->{
            System.out.println("计算结果是: "+v);
        });
        //CompletableFuture里使用的线程池里的线程默认是daemon的。main线程结束后,整个程序也
        //结束了,这里将main线程join后任务里的代码才可以执行完
         Thread.currentThread().join();
    }
 
 
    //compeltableFuture可以支持级联操作
    public static void test3() throws Exception {
        IntStream.range(1,10).boxed().forEach( i ->  CompletableFuture.supplyAsync(CompletableFutureTest::get)
                .thenAccept(CompletableFutureTest::display)
                .whenComplete((v,r)->
                    System.out.println(i +" have done")
                )
        );
        Thread.currentThread().join();
    }
 
    public static  void display(int data){
        int value = ThreadLocalRandom.current().nextInt(10);
        try {
            System.out.println(Thread.currentThread().getName() +"  display  data "+ data+" will sleep "+value);
            TimeUnit.SECONDS.sleep(value);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println(Thread.currentThread().getName() +"  dispaly have done  with  data =  "+data);
    }
 
 
    public static  int get(){
        int value = ThreadLocalRandom.current().nextInt(10);
        try {
            System.out.println(Thread.currentThread().getName() +"  get will sleep "+value);
            TimeUnit.SECONDS.sleep(value);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println(Thread.currentThread().getName() +"  get have done  "+value);
        return value;
    }
 
    //两个线程分别执行任务,任务都执行完后再执行最后的runnable
    public static void test4() throws InterruptedException {
        CompletableFuture.supplyAsync(Object::new)
                .thenAcceptAsync(obj -> {
                    try {
                        System.out.println("obj ====== start");
                        TimeUnit.SECONDS.sleep(5);
                        System.out.println("obj ====== " + obj);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
        }).runAfterBoth(CompletableFuture.supplyAsync(() -> "hello")
                .thenAcceptAsync((v) -> {
                    try {
                        System.out.println("string ====== start");
                        TimeUnit.SECONDS.sleep(3);
                        System.out.println("string ====== " + v);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }), () -> System.out.println("finished"));
        Thread.currentThread().join();
    }
 
 
 
    //一个线程计算奇数和,一个线程计算偶数和,main线程将他们相加
    public static  void test9() throws ExecutionException, InterruptedException {
        CompletableFuture<Integer> oddNumber = CompletableFuture.supplyAsync(()->{
            try {
                System.out.println("开始计算奇数和  ...");
                Thread.sleep(3_000);
                System.out.println("结束计算奇数和  ...");
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            return   1+3+5+7+9;
        });
        CompletableFuture<Integer> evenNumber = CompletableFuture.supplyAsync(()->{
            try {
                System.out.println("开始计算偶数和  ...");
                Thread.sleep(5_000);
                System.out.println("结束计算偶数和  ...");
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            return 2+4+6+8;
        });
        long startTime = System.currentTimeMillis();
        CompletableFuture<Integer> resultFuturn = oddNumber.thenCombine(evenNumber,(odd,even)->{
            return odd + even;
        });
        System.out.println("===============");
        System.out.println("运行结果是:"+resultFuturn.get()+" 总共耗时:"+ (System.currentTimeMillis()-startTime) +"毫秒");
    }
 
}

  


__EOF__

本文作者veblenJan°
本文链接https://www.cnblogs.com/veblen/p/13071689.html
关于博主:评论和私信会在第一时间回复。或者直接私信我。
版权声明:本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!
声援博主:如果您觉得文章对您有帮助,可以点击文章右下角推荐一下。您的鼓励是博主的最大动力!
posted @   venblenJan°  阅读(1957)  评论(0编辑  收藏  举报
编辑推荐:
· SQL Server 2025 AI相关能力初探
· Linux系列:如何用 C#调用 C方法造成内存泄露
· AI与.NET技术实操系列(二):开始使用ML.NET
· 记一次.NET内存居高不下排查解决与启示
· 探究高空视频全景AR技术的实现原理
阅读排行:
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· SQL Server 2025 AI相关能力初探
· AI编程工具终极对决:字节Trae VS Cursor,谁才是开发者新宠?
· 开源Multi-agent AI智能体框架aevatar.ai,欢迎大家贡献代码
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
点击右上角即可分享
微信分享提示