相关文章推荐
强悍的核桃  ·  java.lang.IllegalState ...·  6 月前    · 
玩篮球的红酒  ·  antd ProComponent ...·  1 年前    · 
贪玩的排球  ·  macOS 开发 - ...·  1 年前    · 
路过的茴香  ·  Oops!!! - 简书·  1 年前    · 
犯傻的海龟  ·  25 基本R绘图 | R语言教程·  2 年前    · 
	@SneakyThrows




    

    private void test() {
        CompletableFuture<String> future = CompletableFuture.supplyAsync(() -> {
            return "任务A";
        }).thenApplyAsync(s -> {
            System.out.println(s);
            return "任务B";
        }).thenApplyAsync(s -> {
            System.out.println(s);
            return "任务C";
        });
        System.out.println(future.get());
I/System.out: 任务A
I/System.out: 任务B
I/System.out: 任务C

2、返回复杂类型

       类似的,更复杂的:

    CompletableFuture.supplyAsync(() -> {
        Map<String, String> map = new HashMap<>();
        // TODO 获取数据,并填充 map
        return map;
    }).thenApplyAsync(map -> {
        // TODO 完善 map
        return map;
    }).thenApplyAsync(map -> {
        // TODO 完善 map
        return map;
    });

3、链中 Future 时序关系

       要注意的是,链中的多个 Future 仍然是串行开始,和结束的:

private CompletableFuture<Map<Long, String>> getTagMap() {
    return CompletableFuture.supplyAsync(() -> {
        System.out.println("future 2: " + Thread.currentThread().getName());
        try {
            TimeUnit.SECONDS.sleep(1);
        } catch (InterruptedException e) {
            e.printStackTrace();
        return ImmutableMap.of(1L, "");
    }).thenApplyAsync(map -> {
        System.out.println("future 3: " + Thread.currentThread().getName());
        try {
            TimeUnit.SECONDS.sleep(1);
        } catch (InterruptedException e) {
            e.printStackTrace();
        return map;
    }).thenApplyAsync(map -> {
        System.out.println("future 4: " + Thread.currentThread().getName());
        try {
            TimeUnit.SECONDS.sleep(1);
        } catch (InterruptedException e) {
            e.printStackTrace();
        return map;
    });
@SneakyThrows
public static void main(String[] args) {
    CompletableFuture<?> obj = new HugUserTagController().getTagMap();
    System.out.println("future 1: " + Thread.currentThread().getName());
    TimeUnit.SECONDS.sleep(5);

       执行结果:

future 2: ForkJoinPool.commonPool-worker-3
future 1: main
future 3: ForkJoinPool.commonPool-worker-3
future 4: ForkJoinPool.commonPool-worker-3

4、完全并行

       若想多个 future 同时发起,并在全部准备好时,执行主任务,则需要下面这样:

@SneakyThrows
public static void main(String[] args) {
    long l = System.currentTimeMillis();
    CompletableFuture<String> tokenFuture = CompletableFuture.supplyAsync(() -> {
        System.out.println("future 1: 第   " + (new Date().getTime() - l) + "  毫秒:" + Thread.currentThread().getName());
        try {




    

            TimeUnit.SECONDS.sleep(1);
        } catch (InterruptedException e) {
            e.printStackTrace();
        return "ABC";
    });
    CompletableFuture<String> signFuture = CompletableFuture.supplyAsync(() -> {
        System.out.println("future 2: 第   " + (new Date().getTime() - l) + "  毫秒:" + Thread.currentThread().getName());
        try {
            TimeUnit.SECONDS.sleep(1);
        } catch (InterruptedException e) {
            e.printStackTrace();
        return "DEF";
    });
    CompletableFuture.allOf(tokenFuture, signFuture).thenApplyAsync(x -> {
        System.out.println("future 3: 第 " + (new Date().getTime() - l) + " 毫秒:" + Thread.currentThread().getName());
        System.out.println(tokenFuture);
        System.out.println(signFuture); 
        return "XYZ";
    });
    TimeUnit.SECONDS.sleep(3);
 

也可以放入 List,再整体解析
CompletableFuture.allOf(
completableFutureList.toArray(new CompletableFuture[]{})).thenApplyAsync(x -> {
return completableFutureList.stream().map(future -> {
return future.get();
return Boolean.FALSE;
});
});

       token 和 sign 将同时开始,并在两者都准备好时,执行 future 3。

       执行结果:

future 1: 第   7  毫秒:ForkJoinPool.commonPool-worker-3
future 2: 第   7  毫秒:ForkJoinPool.commonPool-worker-5
future 3: 第 1008 毫秒:ForkJoinPool.commonPool-worker-3
java.util.concurrent.CompletableFuture@4ae82cd0[Completed normally]
java.util.concurrent.CompletableFuture@4ed7a155[Completed normally]

       或,以再一层 future 包裹,从而优雅的同时,不占用业务线程(一般为 Servlet 容器服务的 Task 线程):

* 获取全部标签元数据, 以 map 结构返回 * @return Map<Long, String>, tagId > tagName public CompletableFuture<Map<Long, String>> getTagMetaMap() { return CompletableFuture.supplyAsync(() -> { Map<Long, String> finalMap = new HashMap<>(); Arrays.stream(TagUserTypeEnum.values()).map(x -> CompletableFuture.supplyAsync(() -> userTagService.getTagMsgByType(x).stream() .collect(Collectors.toMap(TagUserMetaModel::getTagId, TagUserMetaModel::getTagName)) ).forEach(x -> { try { finalMap.putAll(x.get()); } catch (InterruptedException | ExecutionException e) { e.printStackTrace(); }); return finalMap; });

5、thenApply不能当作阻塞用

5.1)thenApply和thenApplyAsync的区别

       这两个方法区别就在于谁去执行这个任务:

  • thenApplyAsync:执行的线程是从 ForkJoinPool.commonPool() 中获取不同的线程进行执行。
  • 而 thenApply 分两种情况:
    • 如果supplyAsync 执行速度特别快,那么thenApply 就由主线程进行执行。
    • 如果supplyAsync 执行特别慢的话,就由supplyAsync 的线程来执行。

       接下来我们通过例子来看一下,使用sleep方法来反应supplyAsync 执行速度的快慢。

//thenApply和thenApplyAsync的区别
System.out.println("------------- Sleep");
CompletableFuture<String> supplyAsyncWithSleep = CompletableFuture.supplyAsync(()->{
    try {
        Thread.sleep(10000);
    } catch (InterruptedException e) {
        e.printStackTrace();
    return "supplyAsyncWithSleep Thread Id : " + Thread.currentThread();
});
CompletableFuture<String> thenApply = supplyAsyncWithSleep
        .thenApply(name -> name + "------thenApply Thread Id : " + Thread.currentThread());
CompletableFuture<String> thenApplyAsync = supplyAsyncWithSleep
        .thenApplyAsync(name -> name + "------thenApplyAsync Thread Id : " + Thread.currentThread());
System.out.println("Main Thread Id: "+ Thread.currentThread());
System.out.println(thenApply.get());
System.out.println(thenApplyAsync.get());
System.out.println("------------- No Sleep");
CompletableFuture<String> supplyAsyncNoSleep = CompletableFuture.supplyAsync(()->{
    return "supplyAsyncNoSleep Thread Id : " + Thread.currentThread();
});
CompletableFuture<String> thenApplyNoSleep = supplyAsyncNoSleep
        .thenApply(name -> name + "------thenApply Thread Id : " + Thread.currentThread());
CompletableFuture<String> thenApplyAsyncNoSleep = supplyAsyncNoSleep
        .thenApplyAsync(name -> name + "------thenApplyAsync Thread Id : " + Thread.currentThread());
System.out.println("Main Thread Id: "+ Thread.currentThread());
System.out.println(thenApplyNoSleep.get());
System.out.println(thenApplyAsyncNoSleep.get());
------------- Sleep
Main Thread Id: Thread[main,5,main]
supplyAsyncWithSleep Thread Id : Thread[ForkJoinPool.commonPool-worker-1,5,main]------thenApply Thread Id : Thread[ForkJoinPool.commonPool-worker-1,5,main]
supplyAsyncWithSleep Thread Id : Thread[ForkJoinPool.commonPool-worker-1,5,main]------thenApplyAsync Thread Id : Thread[ForkJoinPool.commonPool-worker-1,5,main]
------------- No Sleep
Main Thread Id: Thread[main,5,main]
supplyAsyncNoSleep Thread Id : Thread[ForkJoinPool.commonPool-worker-2,5,main]------thenApply Thread Id : Thread[main,5,main]
supplyAsyncNoSleep Thread Id : Thread[ForkJoinPool.commonPool-worker-2,5,main]------thenApplyAsync Thread Id : Thread[ForkJoinPool.commonPool-worker-2,5,main]
                    @SneakyThrows    private void test() {        CompletableFuture&lt;String&gt; future = CompletableFuture.supplyAsync(() -&gt; {            return "任务A";        }).thenApplyAsync(s -&gt; {            System.out.println(s);            return "任务B";  .
				
private void test() { CompletableFuture future = CompletableFuture.supplyAsync(new Supplier<String>() { @Override public String get() { try {...
CompletableFuture.supplyAsync FutureJava5新加的一个接口,它提供了一种异步并行计算的功能。如果主线程需要执行一个很耗时的计算任务,我们就可以通过future把这个任务放到异步线程中执行。主线程继续处理其他任务,处理完成后,再通过Future获取计算结果。 老爸有俩孩子:小红和小明。老爸想喝酒了,他让小红去买酒,小红出去了。然后老爸突然想吸烟了,于是老爸让小明去买烟。在面对对象的思想中,一般会把买东西,然后买回来这件事作为一个方法,如果按照顺序结构或者使用多线程同步
所谓异步调用其实就是实现一个可无需等待被调用函数的返回值而让操作继续运行的方法。在 Java 语言中,简单的讲就是另启一个线程来完成调用中的部分计算,使调用继续运行或返回,而不需要等待计算结果。但调用者仍需要取线程的计算结果。 JDK5新增了Future接口,用于描述一个异步计算的结果。虽然 Future 以及相关使用方法提供了异步执行任务的能力,但是对于结果的获取却是很不方便,只能通过阻塞或者轮询的方式得到任务的结果。阻塞的方式显然和
通过调用异步方法(方法后边加Async后缀),串联起来的CompletableFuture可以异步地执行(使用ForkJoinPool.commonPool())。 static void thenApplyAsyncExample() { CompletableFuture cf = CompletableFuture.completedFuture("message").thenApplyAsync(s -> { assertTrue(Thread.currentThr
使用jdk8中的java.util.concurrent.CompletableFuture非常方便进行异步任务编排 1.supplyAsync 开启异步任务 * 1.小白点菜 * 2.厨师做菜 * 3.小白吃饭 public static void test1() { SmallTools.printTimeAndThread("小白进入餐厅"); SmallTools.printTimeAndThread("小白点了 番茄炒蛋+一碗米饭"); //启动一个线
一:创建任务并执行任务 1:无参创建:CompletableFuture<String> noArgsFuture = new CompletableFuture<>(); 2:传入相应任务,无返回值(runAsync方法可以在后台执行异步计算,但是此时并没有返回值。持有一个Runnable对象。) CompletableFuture noReturn = Comp...
我们在精通多线程,没用过CompletableFuture(二)中介绍了创建CompletableFuture的四种方式,我们知道了如何通过CompletableFuture来处理异步任务,之前我们对比CompletableFutureFuture说到,CompletableFuture可以通过异步回调来通知异步任务执行完成,这里我们就一起看看CompletableFuture是如何做到这点的。 ThenApply/ThenApplyAsync 对于ThenApply/ThenApplyAsy
@[toc] CompletableFuture实现了CompletionStage接口和Future接口,前者是对后者的一个扩展,增加了异步回调、流式处理、多个Future组合处理的能力,使Java在处理多任务的协同工作时更加顺畅便利。 一、创建异步任务 1、Future.submit 通常的线程池接口类ExecutorService,其中execute方法的返回值是void,即无法获取异步任务的执行状态,3个重载的submit方法的返回值是Future,可以据此获取任务执行的状态和结果,示...
j610622106: 用 java 社区的 Helidon NiMa 更公正点(Helidon NiMa是基于 virtual thread 也就是协程, 我用 Helidon NiMa vs tokio+salvo 测过,Helidon NiMa 略输少了30几个并发,内存才 260M) 测试请尽量公正点(有点go社区用户的感觉,测试造假想方设法让go赢) 十六、Vert.x、Actix-web、Warp、Axum 性能对比 aaa_vieri: 你这个vert.x只使用了一个cpu线程,要在deploy的时候设置成worker,并且setInstances为逻辑cpu核心数。 Neo4j性能测试 Ella486900: 楼主您好,请问neo4j的测试数据可以分享下嘛?我最近本科毕设在做这个,万分感谢 《我学区块链》—— 二、一些概念和工具 很高兴能帮到您 表情包 八、Rust 集成 Sqlx 跑过的,就是从搭建的demo项目拷贝出来的