多线程之CompletableFuture(上)

CompletableFuture类实现了CompletionStage和Future接口。Future是Java 5添加的类,用来描述一个异步计算的结果,但是获取一个结果时方法较少,要么通过轮询isDone,确认完成后,调用get()获取值,要么调用get()设置一个超时时间。但是这个get()方法会阻塞住调用线程,这种阻塞的方式显然和我们的异步编程的初衷相违背,为了解决这个问题,JDK吸收了guava的设计思想,加入了Future的诸多扩展功能形成了CompletableFuture。
CompletableFutureApi:https://docs.oracle.com/javase/8/docs/api/java/util/concurrent/CompletableFuture.html



CompletableFuture的静态方法

首先了解下都有哪些静态方法:
这里写图片描述

  • runAsync(Runnable runnable):该方法返回CompletableFuture<Void>
public static void main(String[] args) {
        CompletableFuture<Void> voidCompletableFuture = CompletableFuture.runAsync(() -> {
            try {
                System.out.println(Thread.currentThread().getName() + ": runAsync=======开始");
                TimeUnit.SECONDS.sleep(5);
                System.out.println(Thread.currentThread().getName() + ": runAsync=======结束");
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        });
        System.out.println("+++++++++++++++++++++++++++++++");
        voidCompletableFuture.join();
        System.out.println("-------------");
    }

需要注意的是使用的默认的线程池ForkJoinPool.commonPool(),待会详细介绍ForkJoinPool.commonPool();里面的线程都是守护线程,Main方法结束,线程也就随着结束了。

- runAsync(Runnable runnable,Executor executor)
executor是我们自定义的线程池。

public static void main(String[] args) {
        ExecutorService executorService = Executors.newFixedThreadPool(2);
        CompletableFuture<Void> voidCompletableFuture = CompletableFuture.runAsync(() -> {
            try {
                System.out.println(Thread.currentThread().getName() + ": runAsync=======开始");
                TimeUnit.SECONDS.sleep(5);
                System.out.println(Thread.currentThread().getName() + ": runAsync=======结束");
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        },executorService);
        System.out.println("+++++++++++++++++++++++++++++++");
        executorService.shutdown();
        System.out.println("-------------");
    }

这样就可以使用自定义的线程池了,使用默认的还是自定义的,这个本人未找到资料证明哪个效率更高。下面介绍方法如果有Executor 参数,均是这样使用,不再累赘。

  • supplyAsync(Supplier supplier) or supplyAsync(Supplier supplier, Executor executor) :返回CompletableFuture<U>
    这个与上面区别就是有返回值
public static void main(String[] args) {
        CompletableFuture<String> future = CompletableFuture.supplyAsync(() -> {
            try {
                System.out.println(Thread.currentThread().getName() + ": runAsync=======开始");
                TimeUnit.SECONDS.sleep(5);
                System.out.println(Thread.currentThread().getName() + ": runAsync=======结束");
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            return "我是返回值";
        });
        System.out.println("+++++++++++++++++++++++++++++++");
        try {
            System.out.println(future.get());
        } catch (Exception e) {
            e.printStackTrace();
        }
        System.out.println("-------------");
    }

通过get()方法,获取返回值。

  • anyOf(CompletableFuture<?>... cfs): 返回CompletableFuture<Object>
    返回先结束的线程,类似之前学的invokeAny.
public static void main(String[] args) {
        CompletableFuture<Object> objectCompletableFuture = CompletableFuture.anyOf(CompletableFuture.runAsync(() -> {
                    try {
                        System.out.println(Thread.currentThread().getName() + ": 1====开始");
                        TimeUnit.SECONDS.sleep(5);
                        System.out.println(Thread.currentThread().getName() + ": 1====结束");
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }),
                CompletableFuture.supplyAsync(() -> {
                    try {
                        System.out.println(Thread.currentThread().getName() + ": 2====开始");
                        TimeUnit.SECONDS.sleep(3);
                        System.out.println(Thread.currentThread().getName() + ": 2====结束");
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                    return "ssssssssssssss";
                })
        );
        try {
            System.out.println("获取返回值:" + objectCompletableFuture.get());
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

输出结果:
这里写图片描述
注意:当快的线程结束返回结果了,慢的线程照常运行。这里是因为快的线程结束后,get()方法取到值,放行,Main方法就结束了。这时所以全部结束(因为是守护线程)。

  • (CompletableFuture<?>... cfs):CompletableFuture<Void>
    结束的所有线程,类似之前学的invokeAll.
public class CompletableFutureTest1 {
    public static void main(String[] args) {
        CompletableFuture<Void> voidCompletableFuture = CompletableFuture.allOf(CompletableFuture.runAsync(() -> {
                    try {
                        System.out.println(Thread.currentThread().getName() + ": 1====开始");
                        TimeUnit.SECONDS.sleep(5);
                        System.out.println(Thread.currentThread().getName() + ": 1====结束");
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }),
                CompletableFuture.supplyAsync(() -> {
                    try {
                        System.out.println(Thread.currentThread().getName() + ": 2====开始");
                        TimeUnit.SECONDS.sleep(10);
                        System.out.println(Thread.currentThread().getName() + ": 2====结束");
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                    return "ssssssssssssss";
                })
        );
        try {
            System.out.println("返回值:" + voidCompletableFuture.get());
        } catch (Exception e) {
            e.printStackTrace();
        }
    }


}

返回结果:这里写图片描述

  • completedFuture(U value):返回CompletableFuture<U>
public static void main(String[] args) {
        CompletableFuture<String> sss = CompletableFuture.completedFuture("sss");
        try {
            System.out.println(sss.get());
        } catch (Exception e) {
            e.printStackTrace();
        }
    }


ForkJoinPool.commonPool()

请参考:https://segmentfault.com/a/1190000008470012

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值