JUC之CompletableFuture

1 Future接口

在这里插入图片描述
在这里插入图片描述

1.1 FutureTask相关接口关系

在这里插入图片描述

1.2 Future接口的优缺点

1.2.1 优点

结合线程池,可以提升程序的运算效率。

1.2.2 缺点

(1) get方法阻塞
在这里插入图片描述
(2)isDone通常会轮询
在这里插入图片描述
在这里插入图片描述
我们还想需要:
(1) 缺少完成时的回调通知。
(2) 多个任务前后依赖可以组合处理。
(3)选择计算速度最快的那个线程。
在这里插入图片描述

2 Complatable Future

在这里插入图片描述
在这里插入图片描述

2.1 CompletionStage

在这里插入图片描述

2.2 使用案例

2.2.1 runAsync

在这里插入图片描述

2.2.2 supplyAsync

package org.example.completablefuturetest;

import java.util.concurrent.*;

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

        try {
    
    
            CompletableFuture.supplyAsync(() -> {
    
    
                System.out.println(Thread.currentThread().getName() + "-------come in.");
                int result = ThreadLocalRandom.current().nextInt(10);
                try {
    
    
                    TimeUnit.SECONDS.sleep(2);
                } catch (InterruptedException e) {
    
    
                    throw new RuntimeException(e);
                }
                System.out.println("---------2s之后出结果---" + result);
                if (result > 2) {
    
    
                    throw new RuntimeException("sk, throw a run time exception.");
                }
                return result;
            }, threadPool).whenComplete((value, exception) -> {
    
    
                if (exception == null) {
    
    
                    System.out.println("-------计算完成,更新系统value:---" + value);
                }
            }).exceptionally(exception -> {
    
    
                System.out.println("sk, will handle a ex.");
                exception.printStackTrace();
                return null;
            });
            System.out.println(Thread.currentThread().getName() + "线程先去忙其他任务");
        } catch (Exception exception) {
    
    
            exception.printStackTrace();
        } finally {
    
    
            threadPool.shutdown();
        }
    }
}

2.2.3 join和get的区别

就是抛出的异常不一样。 join不需要使用方显示地捕获异常。

public class CompletableFutureMallDemo {
    
    
    public static void main(String[] args) {
    
    
        CompletableFuture cf = CompletableFuture.supplyAsync(new Supplier<String>() {
    
    
            @Override
            public String get() {
    
    
                return "sk, 1234";
            }
        });

        System.out.println(cf.join());
    }
}

2.2.4 CF simple project使用案例

在这里插入图片描述

package org.example.cfmall;

import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;

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.function.Supplier;
import java.util.stream.Collectors;

public class CompletableFutureMallDemo {
    
    
    static List<NetMall> list = Arrays.asList(
        new NetMall("jingdong"),
        new NetMall("dangdang"),
        new NetMall("taobao")
    );

    public static List<String> getPrice(List<NetMall> list, String productName) {
    
    
        // return getPriceStepByStep(list, productName);
        return getPriceAsync(list, productName);
    }

    private static List<String> getPriceAsync(List<NetMall> list, String productName) {
    
    
        return list.stream().map(netMall -> CompletableFuture.supplyAsync(new Supplier<String>() {
    
    
            @Override
            public String get() {
    
    
                return String.format(productName + "in %s price is %.2f",
                    netMall.getNetMallName(), netMall.calcPrice(productName));
            }
        })).collect(Collectors.toList()).stream().map(cf -> cf.join()).collect(Collectors.toList());
    }


    private static List<String> getPriceStepByStep(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 void main(String[] args) {
    
    
        long startTime = System.currentTimeMillis();
        List<String> priceList = getPrice(list, "mysql");
        for (String price : priceList) {
    
    
            System.out.println(price);
        }
        long endTime = System.currentTimeMillis();
        System.out.println("------costTime: " + (endTime - startTime) + " ms");
    }
}

@AllArgsConstructor
@NoArgsConstructor
@Data
class NetMall {
    
    
    private String netMallName;

    public double calcPrice(String productName) {
    
    
        try {
    
    
            TimeUnit.SECONDS.sleep(1);
        } catch (InterruptedException e) {
    
    
            e.printStackTrace();
        }

        return ThreadLocalRandom.current().nextDouble() * 2 + productName.charAt(0);
    }
}

2.2.5 CF 常用API

2.2.5.1 获取结果和主动触发计算

在这里插入图片描述

2.2.5.2 对计算结果进行处理

在这里插入图片描述

2.2.5.3 对计算结果进行消费

在这里插入图片描述
带Async后缀和不带后缀的api的区别在这里插入图片描述
在这里插入图片描述

2.2.5.4 对计算速度进行选用

在这里插入图片描述

2.2.5.4 对计算结果进行合并

在这里插入图片描述

3 参考

[1] https://www.bilibili.com/video/BV1ar4y1x727?p=28&vd_source=f4dcb991bbc4da0932ef216329aefb60

猜你喜欢

转载自blog.csdn.net/kaikai_sk/article/details/131277595