CompletableFuture学习笔记

CompletableFuture

Future接口理论知识

Future接口
Future接口(FutureTask实现类)定义了操作异步任务执行一些方法,如获取异步任务的执行结果、取消任务的执行、判断任务是否被取消、判断任务执行是否完毕等。
解释:接口定义了一堆规范保证异步任务执行过程中的反馈并获得任务的执行结果。

Future为什么出现?
主线程让一个子线程去执行任务,子线程可能比较耗时,启动子线程开始执行任务后,主线程就去做其他事情了,忙其他事情或者先执行完,过了一会才去获取子任务的执行结果或变更的任务状态。

Future接口可以为主线程开一个分支任务,专门为主线程处理耗时和费力的复杂业务。
Future是Java5新加的一个接口,它提供了一种价格异步并行计算的功能。
如果主线程需要执行一个很耗时的计算任务,我们就可以通过futue把这个任务放到异步线程中执行。主线程继续处理其他任务或者先行结束,再通过Future获取计算结果。

Future常用实现类FutureTask异步任务

本源的Future接口相关架构
FutureTask实现了Runnable、Future、RunableFuture接口。RunableFuture接口继承了Runnable和Future接口。
现在需要兼容以下三个特点的类:
FutureTask同时满足了以下三个特点:
多线程(Runable),
有返回(FutureTask(Callable callable)支持构造注入,包含了Callable接口),
异步任务(Future)

示例代码:

package com.atguigu.futureTask;

import java.util.concurrent.Callable;
import java.util.concurrent.FutureTask;

public class CompletableFutureDemo {
    public static void main(String[] args) throws ExecutionException, InterruptedException{
        FutureTask<String> stringFutureTask = new FutureTask<String>(new MyThread());
        new Thread(stringFutureTask,"t1").start();
        //获取返回结果
        System.out.println(stringFutureTask.get());
    }
}

class MyThread implements Callable<String>{

    @Override
    public String call() throws Exception {
        System.out.println("----come in call()");
        return "hello world";
    }
}

Future编码实战和优缺点的分析
优点:future+线程池异步多线程任务配合,能显著提升程序的执行效率。

package com.atguigu.futureTask;

import java.util.concurrent.*;

public class FutureThreadPoolDemo {
    public static void main(String[] args) {
        ExecutorService pool = Executors.newFixedThreadPool(3);

        long start = System.currentTimeMillis();
        FutureTask<String> futureTask1 = new FutureTask<>(() -> {
            try {
                TimeUnit.MILLISECONDS.sleep(500);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            return null;
        });

        FutureTask<String> futureTask2 = new FutureTask<>(() -> {
            try {
                TimeUnit.MILLISECONDS.sleep(5);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            return null;
        });

        FutureTask<String> futureTask3 = new FutureTask<>(() -> {
            try {
                TimeUnit.MILLISECONDS.sleep(100);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            return null;
        });
        pool.submit(futureTask1);
        pool.submit(futureTask2);
        pool.submit(futureTask3);
        try {
            futureTask1.get(); // Waits for task 1 to complete
            futureTask2.get(); // Waits for task 2 to complete
            futureTask3.get(); // Waits for task 3 to complete
        } catch (InterruptedException | ExecutionException e) {
            e.printStackTrace();
        }
        pool.shutdown();
        long end = System.currentTimeMillis();
        System.out.println("----costTime:"+(end-start)+"ms");

    }

}

缺点:

  1. get()阻塞
package com.atguigu.futureTask;

import java.util.concurrent.ExecutionException;
import java.util.concurrent.FutureTask;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;

public class FutureApiDemo {
    public static void main(String[] args) throws ExecutionException, InterruptedException, TimeoutException {
        FutureTask<String> futureTask = new FutureTask<String>(() -> {
            System.out.println(Thread.currentThread().getName() + "\t -----come in");
            try {
                TimeUnit.SECONDS.sleep(5);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            return "task over";
        });
        new Thread(futureTask,"t1").start();

        //get()容易造成阻塞,一般建议放在程序后面,一旦调用不见不散,非要等到结果才会离开,不管你是否计算完成,容易程序阻塞。
//        System.out.println(futureTask.get());
        System.out.println("----主线程忙其他任务了");
//        System.out.println(futureTask.get());
        //假如我不愿意等待很长时间,我希望过时不候,可以自动离开。
        System.out.println(futureTask.get(3,TimeUnit.SECONDS));
    }
}

  1. 缺点:isDone()轮询,轮询的方式会耗费无谓的CPU资源,而且也不见得能及时得到计算结果
    如果想要异步获取结果,通常都会以轮询的方式去获取结果,尽量不要阻塞。
package com.atguigu.futureTask;

import java.util.concurrent.ExecutionException;
import java.util.concurrent.FutureTask;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;

public class FutureApiDemo {
    public static void main(String[] args) throws ExecutionException, InterruptedException, TimeoutException {
        FutureTask<String> futureTask = new FutureTask<String>(() -> {
            System.out.println(Thread.currentThread().getName() + "\t -----come in");
            try {
                TimeUnit.SECONDS.sleep(5);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            return "task over";
        });
        new Thread(futureTask,"t1").start();

        //get()容易造成阻塞,一般建议放在程序后面,一旦调用不见不散,非要等到结果才会离开,不管你是否计算完成,容易程序阻塞。
//        System.out.println(futureTask.get());
        System.out.println("----主线程忙其他任务了");
//        System.out.println(futureTask.get());
        //假如我不愿意等待很长时间,我希望过时不候,可以自动离开。 抛出异常,不优雅
//        System.out.println(futureTask.get(3,TimeUnit.SECONDS));
        //get()容易导致阻塞,能不能什么时候完成,什么时候调用
        //缺点:轮询的方式会耗费无谓的CPU资源,而且也不见得能及时得到计算结果
        //如果想要异步获取结果,通常都会以轮询的方式去获取结果,尽量不要阻塞。
        while (true){
            if(futureTask.isDone()){
                System.out.println(futureTask.get());
                break;
            }else {
                TimeUnit.MILLISECONDS.sleep(500);
                System.out.println("正在处理中,不要再催了");
            }
        }
    }
}

结论:Future对于结果的获取不是很有友好。

想要完成一些复杂的任务

对于简单业务场景使用Future完全OK

  • 回调通知:应对Future的完成时间,完成了可以告诉我,也就是我们的回调通知;
    通过轮询的方式去判断任务是否完成这样占CPU并且代码不够优雅 。

  • 创建异步任务:Future+线程池配合

  • 多个任务前后依赖可以组合处理:想将多个异步任务的计算结果组合起来,后一个异步任务的计算结果需要前一个异步任务的值;将两个或多个异步计算合成一个异步计算,这几个异步计算互相独立,同时后面这个又依赖前一个处理的结果。

  • 对计算速度选最快:当Future集合中某个任务最快结束时,返回结果,返回第一名处理结果。

为了解决Future的get()阻塞和isDone()轮询耗费无谓的CPU资源的缺点,为了更复杂任务的四个功能,CompletableFuture对Future改进。

CompletableFuture对Future改进:以优雅的方式处理这些需求

CompletableFuture为什么出现?

get()方法在Future计算完成之前会一直处于阻塞状态下,
isDone()方法容易耗费CPU资源,
对于真正的异步处理我们希望时可以通过传入回调函数,在Future结束时自动调用该回调函数,这样,我们就不用等待结果。
阻塞的方式和异步编程的设计理念相违背,而轮询的方式会耗费无谓的CPU资源。因此,JDK8设计出CompletableFuture。
CompletableFuture提供了一种观察者模式类似的机制,可以让任务执行完成后通知监听的一方。

CompletableFuture和CompletionStage架构

-CompletionStage

  • CompletionStage代表异步计算过程中的某一个阶段,一个阶段完成后可能会触发另外一个阶段。
  • 一个阶段的计算执行可以是一个Function,Comsumer或者Runnable。
  • 一个阶段的执行可能是被单个阶段的完成触发,也可能时由多个阶段一起触发
    代表异步计算过程中的某一个阶段,一个阶段完成以后可能会触发另外一个阶段,有些类似Linux系统的管道分隔符传参数。

CompletableFuture

  • 在Java8中,CompletableFuture提供了非常强大的Future扩展功能,可以帮助我们简化异步变成的复杂性,并且提供了函数式编程的能力,可以通过回调的方式处理计算结果,也提供了转换和组合CompletabelFuture的方法。
  • 他可能代表一个明确完成的Future,也有可能代表一个完成阶段(CompletionStage),它支持在计算完成后触发一些函数或执行某些动作。
  • CompletableFuture实现了Future和CompletionStage接口

核心的四个静态方法,来创建一个异步任务

  • 直接创建,不推荐使用
CompletableFuture completableFuture = new CompletableFuture();
  1. runAsync方法,无返回值,使用默认线程池
  2. runAsync方法,无返回值,传入线程池
  3. supplyAsync方法,有返回值,使用默认线程池
  4. supplyAsync方法,有返回值,传入线程池
package com.atguigu.CompletableFuture;

import java.util.concurrent.*;

public class CompletavleFutureBuildDemo {
    public static void main(String[] args) throws ExecutionException, InterruptedException {
        //    CompletableFuture completableFuture = new CompletableFuture();
        /**
         * *第一种静态方法
        CompletableFuture<Void> completableFuture = CompletableFuture.runAsync(()->{
            System.out.println(Thread.currentThread().getName());
            try {
                TimeUnit.SECONDS.sleep(1);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        });
        System.out.println(completableFuture.get());
         */

        /**
         * *第二种静态方法
        ExecutorService executorService = Executors.newFixedThreadPool(3);
        CompletableFuture<Void> completableFuture = CompletableFuture.runAsync(()->{
            System.out.println(Thread.currentThread().getName());
            try {
                TimeUnit.SECONDS.sleep(1);
            }catch (InterruptedException e){
                e.printStackTrace();
            }
        },executorService);
        System.out.println(completableFuture.get());
        executorService.shutdown();
         */

        /**
         * *第三种静态方法
        CompletableFuture<String> completableFuture = CompletableFuture.supplyAsync(()->{
            System.out.println(Thread.currentThread().getName());
            try {
                TimeUnit.SECONDS.sleep(1);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            return "hello,supplyAsync";
        });
        System.out.println(completableFuture.get());
         */

        ExecutorService executorService = Executors.newFixedThreadPool(2);
        CompletableFuture<String> completableFuture = CompletableFuture.supplyAsync(()->{
            System.out.println(Thread.currentThread().getName());
            try {
                TimeUnit.SECONDS.sleep(1);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            return "hello,supplyAsync";
        },executorService);
        System.out.println(completableFuture.get());
        executorService.shutdown();

    }

}

CompletableFuture Code演示,减少阻塞和轮询

从Java8开始引入了CompletableFuture,它是Future的功能增强版,减少了阻塞和轮询,可以传入回调对象,当异步任务完成或者发生异常时,自动调用回调对象的回调方法。

completableFuture日常通用使用方法

  • 如果使用默认ForkJoinPool线程池,主线程结束,completableFuture默认使用的线程池会立刻关闭。
package com.atguigu.CompletableFuture;

import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ThreadLocalRandom;
import java.util.concurrent.TimeUnit;

public class CompletableFutureUseDemo {
    public static void main(String[] args) {

        CompletableFuture.supplyAsync(()->{
            System.out.println(Thread.currentThread().getName()+"----come in");
            int result = ThreadLocalRandom.current().nextInt(10);
            try {
                TimeUnit.SECONDS.sleep(1);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println("-----1秒钟后出结果:"+result);
            return result;
        }).whenComplete((v,e)->{
            if(e==null){
                System.out.println("----计算完成,更逊系统UpdateValue"+v);
            }
        }).exceptionally(e->{
            e.printStackTrace();
            System.out.println("异常情况:"+e.getCause()+"\t"+e.getMessage());
            return null;
        });
        System.out.println(Thread.currentThread().getName()+"线程先去忙其他任务");

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

  • 使用自定义线程池解决这个问题
package com.atguigu.CompletableFuture;

import java.util.concurrent.*;

public class CompletableFutureUseDemo {
    public static void main(String[] args) {

        ExecutorService executorService = Executors.newFixedThreadPool(3);

        try {
            CompletableFuture.supplyAsync(()->{
                System.out.println(Thread.currentThread().getName()+"----come in");
                int result = ThreadLocalRandom.current().nextInt(10);
                try {
                    TimeUnit.SECONDS.sleep(1);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                System.out.println("-----1秒钟后出结果:"+result);
                return result;
            },executorService).whenComplete((v,e)->{
            // 上一步的返回值传给v,e时异常
                if(e==null){
                    System.out.println("----计算完成,更逊系统UpdateValue"+v);
                }
            }).exceptionally(e->{
                e.printStackTrace();
                System.out.println("异常情况:"+e.getCause()+"\t"+e.getMessage());
                return null;
            });
            System.out.println(Thread.currentThread().getName()+"线程先去忙其他任务");
        }catch (Exception e){
            e.printStackTrace();
        }finally {
            executorService.shutdown();
        }
    }
}

CompletableFuture的优点

  • 异步任务结束时,会自动回调某个对象的方法;
  • 主线程设置好回调后,不再关心异步任务的执行,异步任务之间可以顺序执行。
  • 异步任务出错时,会自动回调某个对象的方法;

案例精讲-电商网站的比价需求

函数式编程已经主流

Lambda表达式+Stream流式调用+Chain链式调用+Java8函数式编程

函数式接口:使得Java的函数式编程更加灵活和强大,可以通过Lambda表达式和方法引用简洁地表达各种操作逻辑。

  • Runnable 无参数,无返回值
@FunctionalInterface
public interface Runnable{
	public abstract void run();
}
  • Function<T,R>接受一个参数,并且有返回值
@FunctionalInterface
public interface Function<T,R>{
	R apply(T,t);
}

Consumer接受一个参数,没有返回值

@FunctionalInterface
public interface Comsumer<T>{
	void accept(T t);
}

BiConsumer<T,U>接受两个参数,没有返回值

@FunctionalInterface
public interface BiComsumer<T,U>{
	void accept(T t, U u);
}

Supplier没有参数,有一个返回值

@FunctionalInterface
public interface Supplier<T>{
	T get();
}

链式编程

student.setId(12).setStudentName("li4").setMajor("Java");

join和get对比

join和get是一样的,get需要抛出异常,join不会有波浪线的错误,不需要抛出异常。

Java函数式编程——异步编程使用实例,价格比较

获取不同商家某个产品的价格。下面代码分别使用同步和异步的方法实现。

package com.atguigu.CompletableFuture;


import java.util.Arrays;
import java.util.List;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ThreadLocalRandom;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;

public class CompletableFutureMallDemo {
    static List<NetMall> list = Arrays.asList(
            new NetMall("jingdong"),
            new NetMall("dangdang"),
            new NetMall("taobap")
    );
    public static List<String> getPrice(List<NetMall> list, String productName){
        return list.stream().
                map(netMall -> String.format(productName + " in %s price is %.2f", netMall.getNetMallName(), netMall.calcPrice(productName))).
                collect(Collectors.toList());
    }
    public static List<String> getPriceByCompletableFuture(List<NetMall> list, String productName){
        return list.stream().
                map(netMall -> CompletableFuture.supplyAsync(()->String.format(productName+" in %s price is %.2f", netMall.getNetMallName(), netMall.calcPrice(productName))))
                        .collect(Collectors.toList()).stream().map(s->s.join()).collect(Collectors.toList());
    }
    public static void main(String[] args) {
        long start = System.currentTimeMillis();
        List<String> mySQL = getPrice(list, "MySQL");
        for (String element: mySQL){
            System.out.println(element);
        }
        long end = System.currentTimeMillis();
        System.out.println("------costTime:"+(end-start)+"毫秒");
        System.out.println("====================================================");
        long start1 = System.currentTimeMillis();
        List<String> mySQL1 = getPriceByCompletableFuture(list, "MySQL");
        for (String element: mySQL1){
            System.out.println(element);
        }
        long end1 = System.currentTimeMillis();
        System.out.println("------costTime:"+(end1-start1)+"毫秒");
    }
}

class NetMall{
    private String netMallName;

    public NetMall(String netMallName){
        this.netMallName = netMallName;
    }

    public String getNetMallName() {
        return netMallName;
    }

    public double calcPrice(String productName){
        try {
            TimeUnit.SECONDS.sleep(1);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        return ThreadLocalRandom.current().nextDouble()*2+productName.charAt(0);
    }
}


CompletableFuture常用方法

获得结果和触发计算

**获取结果 **
get()
get(long timeout, TimeUnit unit) 过时不候
join() 与get功能几乎一致
getNow(T valuelfAbsent):没有计算完成的情况下,给我一个替代结果。立即获取结果不阻塞,计算完,返回计算完成后的结果;没算完,返回设定的valuefAbsent值

package com.atguigu.CompletableFuture;

import java.util.concurrent.CompletableFuture;
import java.util.concurrent.TimeUnit;

public class CompletableFutureAPIDemo {
    public static void main(String[] args) {
        CompletableFuture<String> completableFuture = CompletableFuture.supplyAsync(() -> {
            System.out.println("---开始执行");
            try {
                TimeUnit.SECONDS.sleep(1);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            return "abc";
        });
        //不加下面这段,输出结果是“xxxx”,加了输出结果是“abc”
        try {
            TimeUnit.SECONDS.sleep(2);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println(completableFuture.getNow("xxxx"));
    }
}

主动触发计算
complete(T value) true,返回设置的值(completeValue);false,返回异步接口return的值(abc)

package com.atguigu.CompletableFuture;

import java.util.concurrent.CompletableFuture;
import java.util.concurrent.TimeUnit;

public class CompletableFutureAPIDemo {
    public static void main(String[] args) {
        CompletableFuture<String> completableFuture = CompletableFuture.supplyAsync(() -> {
            try {
                TimeUnit.SECONDS.sleep(1);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            return "abc";
        });
        try {
            TimeUnit.SECONDS.sleep(2);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
//        System.out.println(completableFuture.getNow("xxxx"));

        System.out.println(completableFuture.complete("completeValue")+"\t"+completableFuture.join());
    }
}

对计算结果进行处理

**thenApply:**计算结果存在依赖关系,这两个线程串行化,出现异常停止。

package com.atguigu.CompletableFuture;

import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;

public class CompletableFutureAPI2Demo {
    public static void main(String[] args) {
        ExecutorService executorService = Executors.newFixedThreadPool(3);
        try {
            CompletableFuture.supplyAsync(()->{
                try {
                    TimeUnit.SECONDS.sleep(1);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                System.out.println("111");
                return 1;
            },executorService).thenApply(f->{
                int i = 10/0;
                System.out.println("222");
                return f+2;
            }).thenApply(f->{
                System.out.println("333");
                return f+3;
            }).whenComplete((v,e)->{
                if(e==null){
                    System.out.println("---计算结果:"+v);
                }
            }
            ).exceptionally(e->{
                e.printStackTrace();
                System.out.println(e.getMessage());
                return null;
            });
            System.out.println(Thread.currentThread().getName()+"先去忙其他任务");
        }finally {
            executorService.shutdown();
        }

    }
}

在这里插入图片描述

**handle:**计算结果存在依赖关系,这两个线程串行化,出现异常,继续执行后面的handle

package com.atguigu.CompletableFuture;

import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;

public class CompletableFutureAPI2Demo {
    public static void main(String[] args) {
        ExecutorService executorService = Executors.newFixedThreadPool(3);
        try {
            CompletableFuture.supplyAsync(()->{
                try {
                    TimeUnit.SECONDS.sleep(1);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                System.out.println("111");
                return 1;
            },executorService).handle((f,e)->{
                int i =10/0;
                System.out.println("222");
                return f+2;
            }).handle((f,e)->{
                System.out.println("333");
                return f+3;
            }).whenComplete((v,e)->{
                if(e==null){
                    System.out.println("---计算结果:"+v);
                }
            }
            ).exceptionally(e->{
                e.printStackTrace();
                System.out.println(e.getMessage());
                return null;
            });
            System.out.println(Thread.currentThread().getName()+"先去忙其他任务");
        }finally {
            executorService.shutdown();
        }

    }
}

在这里插入图片描述

对计算结果进行消费

**thenAccept():**接收任务的处理结果,并消费处理,无返回结果。

package com.atguigu.CompletableFuture;

import java.util.concurrent.CompletableFuture;

public class CompletableFutureAPI3Demo {
    public static void main(String[] args) {
        CompletableFuture.supplyAsync(()->{
            return 1;
        }).thenApply(f->{
            return f+1;
        }).thenApply(f ->{
            return f+2;
        }).thenAccept(t->{
            System.out.println(t);
        });
    }
}

在这里插入图片描述
对比:Code之任务之间的顺序执行:

  • thenRun(Runnable runnable):任务A执行完执行B,并且B不需要A的结果。
  • thenAccpet(Consumer action):任务A执行完B,B需要A的结果,但是任务B无返回值。
  • theApply(Function fn):任务A执行完B,B需要A的结果,同时任务B有返回值。
System.out.println(CompletableFuture.supplyAsync(() -> "resultA").thenRun(() -> {}).join());  //null
        System.out.println(CompletableFuture.supplyAsync(() -> "resultA").thenAccept((r) -> {System.out.println(r);}).join());  //resultA null
        System.out.println(CompletableFuture.supplyAsync(() -> "resultA").thenApply(r ->r+"resultB").join());  //resultAresultB

CompletableFuture和线程池说明
以thenRun和thenRunAsync为例,有什么区别?

package com.atguigu.CompletableFuture;

import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;

public class CompletableFutureWithThreadPoolDemo {
    public static void main(String[] args) {
        ExecutorService executorService = Executors.newFixedThreadPool(3);
        CompletableFuture<Void> completableFuture = CompletableFuture.supplyAsync(() -> {
            try {
                TimeUnit.MILLISECONDS.sleep(20);
                System.out.println("1号任务" + "\t" + Thread.currentThread().getName());
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            return "abcd";
        }, executorService).thenRunAsync(() -> {
            try {
                TimeUnit.MILLISECONDS.sleep(20);
                System.out.println("2号任务" + "\t" + Thread.currentThread().getName());
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }).thenRun(() -> {
            try {
                TimeUnit.MILLISECONDS.sleep(20);
                System.out.println("3号任务" + "\t" + Thread.currentThread().getName());
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }).thenRunAsync(() -> {
            try {
                TimeUnit.MILLISECONDS.sleep(20);
                System.out.println("4号任务" + "\t" + Thread.currentThread().getName());
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        });
        System.out.println(completableFuture.join());
        executorService.shutdown();
    }
}

在这里插入图片描述

  1. 没有传入自定义线程池,都使用默认线程池ForkJoinPool;
  2. 传入了一个自定义线程池,
    如果你执行第一个任务的时候,传入了一个自定义线程池:
    调用thenRun方法执行第二个任务时,则第二个任务和第一个任务是共用同一个线程池。
    调用thenRunAsync方法执行第二个任务时,则第一个任务是你自己传入的线程池,第二个任务使用默认线程池ForkJoinPool。
  3. 备注
    有可能处理的太快,系统优化切换原则,直接使用main线程处理

对计算速度进行选用

playA.applyToEither(playB, f -> {
return f + " is winner";
});

package com.atguigu.CompletableFuture;

import java.util.concurrent.CompletableFuture;
import java.util.concurrent.TimeUnit;

public class CompletableFutureFastDemo {
    public static void main(String[] args) {
        CompletableFuture<String> playA = CompletableFuture.supplyAsync(() -> {
            System.out.println("A come in");
            try {
                TimeUnit.SECONDS.sleep(1);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            return "playA";
        }
        );
        CompletableFuture<String> playB = CompletableFuture.supplyAsync(() -> {
                    System.out.println("B come in");
                    try {
                        TimeUnit.SECONDS.sleep(2);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                    return "playB";
                }
        );
        CompletableFuture<String> completableFuture = playA.applyToEither(playB, f -> {
            return f + " is winner";
        });
        System.out.println(completableFuture.join());
    }
}

对计算结果进行合并

thenCombine()
拆分代码

package com.atguigu.CompletableFuture;

import java.util.concurrent.CompletableFuture;
import java.util.concurrent.TimeUnit;

public class ComplatebleFutureThenCombineDemo {
    public static void main(String[] args) {
        CompletableFuture<Integer> completableFuture1 = CompletableFuture.supplyAsync(() -> {
            System.out.println(Thread.currentThread().getName() + "\t" + "启动");
            try {
                TimeUnit.SECONDS.sleep(2);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            return 10;
        });
        CompletableFuture<Integer> completableFuture2 = CompletableFuture.supplyAsync(() -> {
            System.out.println(Thread.currentThread().getName() + "\t" + "启动");
            try {
                TimeUnit.SECONDS.sleep(2);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            return 20;
        });
        CompletableFuture<Integer> completableFuture = completableFuture1.thenCombine(completableFuture2, (x, y) -> {
            System.out.println("结果合并");
            return 20;
        });
        System.out.println(completableFuture.join());
    }
}

合并代码

package com.atguigu.CompletableFuture;

import java.util.concurrent.CompletableFuture;
import java.util.concurrent.TimeUnit;

public class ComplatebleFutureThenCombineDemo2 {
    public static void main(String[] args) {
        CompletableFuture<Integer> completableFuture = CompletableFuture.supplyAsync(() -> {
            System.out.println(Thread.currentThread().getName() + "\t" + "启动");
            try {
                TimeUnit.SECONDS.sleep(1);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            return 10;
        }).thenCombine(CompletableFuture.supplyAsync(() -> {
            System.out.println(Thread.currentThread().getName() + "\t" + "启动");
            try {
                TimeUnit.SECONDS.sleep(2);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            return 20;
        }), (x, y) -> {
            return x + y;
        }).thenCombine(CompletableFuture.supplyAsync(() -> {
            System.out.println(Thread.currentThread().getName() + "\t" + "启动");
            try {
                TimeUnit.SECONDS.sleep(3);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            return 30;
        }), (a, b) -> {
            return a + b;
        });
        System.out.println(completableFuture.join());
    }
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值