JUC之CompletableFuture

文章目录

  • 1 Future接口
    • 1.1 FutureTask相关接口关系
    • 1.2 Future接口的优缺点
      • 1.2.1 优点
      • 1.2.2 缺点
  • 2 Complatable Future
    • 2.1 CompletionStage
    • 2.2 使用案例
      • 2.2.1 runAsync
      • 2.2.2 supplyAsync
      • 2.2.3 join和get的区别
      • 2.2.4 CF simple project使用案例
      • 2.2.5 CF 常用API
        • 2.2.5.1 获取结果和主动触发计算
        • 2.2.5.2 对计算结果进行处理
        • 2.2.5.3 对计算结果进行消费
        • 2.2.5.4 对计算速度进行选用
        • 2.2.5.4 对计算结果进行合并
  • 3 参考

1 Future接口

JUC之CompletableFuture_第1张图片
JUC之CompletableFuture_第2张图片

1.1 FutureTask相关接口关系

JUC之CompletableFuture_第3张图片

1.2 Future接口的优缺点

1.2.1 优点

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

1.2.2 缺点

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

2 Complatable Future

在这里插入图片描述
JUC之CompletableFuture_第6张图片

2.1 CompletionStage

JUC之CompletableFuture_第7张图片

2.2 使用案例

2.2.1 runAsync

JUC之CompletableFuture_第8张图片

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使用案例

JUC之CompletableFuture_第9张图片

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 获取结果和主动触发计算

JUC之CompletableFuture_第10张图片

2.2.5.2 对计算结果进行处理

JUC之CompletableFuture_第11张图片

2.2.5.3 对计算结果进行消费

JUC之CompletableFuture_第12张图片
带Async后缀和不带后缀的api的区别JUC之CompletableFuture_第13张图片
JUC之CompletableFuture_第14张图片

2.2.5.4 对计算速度进行选用

JUC之CompletableFuture_第15张图片

2.2.5.4 对计算结果进行合并

JUC之CompletableFuture_第16张图片

3 参考

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

你可能感兴趣的:(Java并发编程,java)