多线程之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的静态方法

首先了解下都有哪些静态方法:
多线程之CompletableFuture(上)_第1张图片

  • runAsync(Runnable runnable):该方法返回CompletableFuture
public static void main(String[] args) {
        CompletableFuture 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 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
    这个与上面区别就是有返回值
public static void main(String[] args) {
        CompletableFuture 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
    返回先结束的线程,类似之前学的invokeAny.
    public static void main(String[] args) {
            CompletableFuture 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();
            }
        } 
      

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

    • (CompletableFuture... cfs):CompletableFuture
      结束的所有线程,类似之前学的invokeAll.
    public class CompletableFutureTest1 {
        public static void main(String[] args) {
            CompletableFuture 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();
            }
        }
    
    
    }

    返回结果:多线程之CompletableFuture(上)_第3张图片

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


    ForkJoinPool.commonPool()

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

    你可能感兴趣的:(多线程)