CompletableFuture异步编排

CompletableFuture异步编排

1. 基本介绍

2. 创建异步任务

2.1 runAsync方法
  • 方法
public static CompletableFuture<Void> runAsync(Runnable runnable,
                                                   Executor executor) {
        return asyncRunStage(screenExecutor(executor), runnable);
    }
  • 测试代码
package com.finger.fingermall.search.thread;

import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import lombok.extern.slf4j.Slf4j;

/**
 * User: dell Date: 2023/10/28 Time: 10:10 auther: lixh Description: No Description
 */
@Slf4j
public class CompletableFutureTest {

    public static ExecutorService executor = Executors.newFixedThreadPool(10);

    public static void main(String[] args) {
        System.out.println("main....start.......");
        CompletableFuture<Void> future = CompletableFuture.runAsync(() -> {
            System.out.println("当前线程:" + Thread.currentThread().getId());
            int i = 10 / 2;
            System.out.println("运行结果:" + i);
        }, executor);
        System.out.println("main....end.........");
    }

}

  • 运行结果
main....start.......
main....end.........
当前线程:22
运行结果:5
  • 总结
    当前方法没有返回值,跟异步执行new Thread()结果相同,后台因为有线程未销毁,为持续运行状态,此方法为创建异步任务。
2.2 supplyAsync方法
  • 方法
public static <U> CompletableFuture<U> supplyAsync(Supplier<U> supplier,
                                                       Executor executor) {
        return asyncSupplyStage(screenExecutor(executor), supplier);
    }
  • 测试代码
package com.finger.fingermall.search.thread;

import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import lombok.extern.slf4j.Slf4j;

/**
 * User: dell Date: 2023/10/28 Time: 10:10 auther: lixh Description: No Description
 */
@Slf4j
public class CompletableFutureTest {

    public static ExecutorService executor = Executors.newFixedThreadPool(10);

    public static void main(String[] args) throws ExecutionException, InterruptedException {
        System.out.println("main....start.......");
        CompletableFuture<Integer> future = CompletableFuture.supplyAsync(() -> {
            System.out.println("当前线程:" + Thread.currentThread().getId());
            int i = 10 / 2;
//            int i = 10 / 0;
            System.out.println("supplyAsync运行结果:" + i);
            return i;
        }, executor);
        //获取返回值
        Integer i = future.get();
        System.out.println("main....end........."+future.get());
    }

}

  • 运行结果
main....start.......
当前线程:22
supplyAsync运行结果:5
main....end.........5
  • 总结
    从以上方法可以看出,当前方法有返回值,通过future.get();可以获取到返回值,此方法为创建异步任务。

3. 方法执行完成后的处理

3.1 whenComplete、exceptionally方法
  • 方法
public CompletableFuture<T> whenComplete(
        BiConsumer<? super T, ? super Throwable> action) {
        return uniWhenCompleteStage(null, action);
    }
    
public CompletableFuture<T> exceptionally(
        Function<Throwable, ? extends T> fn) {
        return uniExceptionallyStage(fn);
    }
  • 测试代码

whenComplete无异常

package com.finger.fingermall.search.thread;

import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import lombok.extern.slf4j.Slf4j;

/**
 * User: dell Date: 2023/10/28 Time: 10:10 auther: lixh Description: No Description
 */
@Slf4j
public class CompletableFutureTest {

    public static ExecutorService executor = Executors.newFixedThreadPool(10);

    public static void main(String[] args) throws ExecutionException, InterruptedException {
        System.out.println("main....start.......");
        CompletableFuture<Integer> future = CompletableFuture.supplyAsync(() -> {
            System.out.println("当前线程:" + Thread.currentThread().getId());
            int i = 10 / 2;
//            int i = 10 / 0;
            System.out.println("supplyAsync运行结果:" + i);
            return i;
        }, executor).whenComplete((result, exception) -> {
            //虽然能得到异常信息,但是没法修改返回数据
            System.out.println("异步任务完成了...结果是:"+result+";异常是:"+exception);
        });
        //获取返回值
        Integer i = future.get();
        System.out.println("main....end........."+future.get());
    }

}

whenComplete有异常

package com.finger.fingermall.search.thread;

import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import lombok.extern.slf4j.Slf4j;

/**
 * User: dell Date: 2023/10/28 Time: 10:10 auther: lixh Description: No Description
 */
@Slf4j
public class CompletableFutureTest {

    public static ExecutorService executor = Executors.newFixedThreadPool(10);

    public static void main(String[] args) throws ExecutionException, InterruptedException {
        System.out.println("main....start.......");
        CompletableFuture<Integer> future = CompletableFuture.supplyAsync(() -> {
            System.out.println("当前线程:" + Thread.currentThread().getId());
//            int i = 10 / 2;
            int i = 10 / 0;
            System.out.println("supplyAsync运行结果:" + i);
            return i;
        }, executor).whenComplete((result, exception) -> {
            //虽然能得到异常信息,但是没法修改返回数据
            System.out.println("异步任务完成了...结果是:"+result+";异常是:"+exception);
        });
        //获取返回值
        Integer i = future.get();
        System.out.println("main....end........."+future.get());
    }

}

execptionally感知异常并返回默认值

package com.finger.fingermall.search.thread;

import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import lombok.extern.slf4j.Slf4j;

/**
 * User: dell Date: 2023/10/28 Time: 10:10 auther: lixh Description: No Description
 */
@Slf4j
public class CompletableFutureTest {

    public static ExecutorService executor = Executors.newFixedThreadPool(10);

    public static void main(String[] args) throws ExecutionException, InterruptedException {
        System.out.println("main....start.......");
        CompletableFuture<Integer> future = CompletableFuture.supplyAsync(() -> {
            System.out.println("当前线程:" + Thread.currentThread().getId());
//            int i = 10 / 2;
            int i = 10 / 0;
            System.out.println("supplyAsync运行结果:" + i);
            return i;
        }, executor).whenComplete((result, exception) -> {
            //虽然能得到异常信息,但是没法修改返回数据
            System.out.println("异步任务完成了...结果是:"+result+";异常是:"+exception);
        }).exceptionally(t -> {
            //可以感知异常,同时返回默认值
            return 10;
        });
        //获取返回值
        Integer i = future.get();
        System.out.println("main....end........."+future.get());
    }

}

  • 运行结果

whenComplete无异常:

main....start.......
当前线程:22
supplyAsync运行结果:5
异步任务完成了...结果是:5;异常是:null
main....end.........5

whenComplete有异常:

main....start.......
当前线程:22
异步任务完成了...结果是:null;异常是:java.util.concurrent.CompletionException: java.lang.ArithmeticException: / by zero
Exception in thread "main" java.util.concurrent.ExecutionException: java.lang.ArithmeticException: / by zero
	at java.util.concurrent.CompletableFuture.reportGet(CompletableFuture.java:357)
	at java.util.concurrent.CompletableFuture.get(CompletableFuture.java:1908)
	at com.finger.fingermall.search.thread.CompletableFutureTest.main(CompletableFutureTest.java:30)
Caused by: java.lang.ArithmeticException: / by zero
	at com.finger.fingermall.search.thread.CompletableFutureTest.lambda$main$0(CompletableFutureTest.java:22)
	at java.util.concurrent.CompletableFuture$AsyncSupply.run$$$capture(CompletableFuture.java:1604)
	at java.util.concurrent.CompletableFuture$AsyncSupply.run(CompletableFuture.java)
	at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)
	at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)
	at java.lang.Thread.run(Thread.java:748)

execptionally感知异常并返回默认值:

main....start.......
当前线程:22
异步任务完成了...结果是:null;异常是:java.util.concurrent.CompletionException: java.lang.ArithmeticException: / by zero
main....end.........10
  • 总结
    whenComplete:虽然能得到异常信息,但是没法修改返回数据
    exceptionally:可以感知异常,同时返回默认值
3.2 handle方法
  • 方法
public <U> CompletableFuture<U> handle(
        BiFunction<? super T, Throwable, ? extends U> fn) {
        return uniHandleStage(null, fn);
    }
  • 测试代码

int i = 10 / 2;

package com.finger.fingermall.search.thread;

import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import lombok.extern.slf4j.Slf4j;

/**
 * User: dell Date: 2023/10/28 Time: 10:10 auther: lixh Description: No Description
 */
@Slf4j
public class CompletableFutureTest {

    public static ExecutorService executor = Executors.newFixedThreadPool(10);

    public static void main(String[] args) throws ExecutionException, InterruptedException {
        System.out.println("main....start.......");
        /**
         * 方法执行完成后的处理
         */
        CompletableFuture<Integer> future = CompletableFuture.supplyAsync(() -> {
            System.out.println("当前线程:" + Thread.currentThread().getId());
            int i = 10 / 2;
//            int i = 10 / 0;
            System.out.println("main运行结果:" + i);
            return i;
        }, executor).handle((res, e) -> {
            if(null != res) {
                return res * 2;
            }
            if(null != e) {
                return 0;
            }
            return 0;
        });
        System.out.println("main....end........."+future.get());
    }

}

int i = 10 / 0;

package com.finger.fingermall.search.thread;

import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import lombok.extern.slf4j.Slf4j;

/**
 * User: dell Date: 2023/10/28 Time: 10:10 auther: lixh Description: No Description
 */
@Slf4j
public class CompletableFutureTest {

    public static ExecutorService executor = Executors.newFixedThreadPool(10);

    public static void main(String[] args) throws ExecutionException, InterruptedException {
        System.out.println("main....start.......");
        /**
         * 方法执行完成后的处理
         */
        CompletableFuture<Integer> future = CompletableFuture.supplyAsync(() -> {
            System.out.println("当前线程:" + Thread.currentThread().getId());
//            int i = 10 / 2;
            int i = 10 / 0;
            System.out.println("main运行结果:" + i);
            return i;
        }, executor).handle((res, e) -> {
            if(null != res) {
                return res * 2;
            }
            if(null != e) {
                return 0;
            }
            return 0;
        });
        System.out.println("main....end........."+future.get());
    }

}

  • 运行结果
    int i = 10 / 2;
main....start.......
当前线程:22
main运行结果:5
main....end.........10

int i = 10 / 0;

main....start.......
当前线程:22
main....end.........0
  • 总结
    handle对正常的结果可以直接返回或者处理后返回,对异常的结果也可以返回一个对应值,然后还可以返回一个默认值

4. 串行化

4.1 thenRun
  • 方法
    public CompletableFuture<Void> thenRun(Runnable action) {
        return uniRunStage(null, action);
    }

    public CompletableFuture<Void> thenRunAsync(Runnable action) {
        return uniRunStage(asyncPool, action);
    }

    public CompletableFuture<Void> thenRunAsync(Runnable action,
                                                Executor executor) {
        return uniRunStage(screenExecutor(executor), action);
    }
  • 区别

    • thenRun(Runnable action)
      可以看到它调用没有传入uniRunStage(Executor e, Runnable f) 方法时候Executor参数传的null,所以它是使用的是执行上一个任务的线程池。也就是说,如果你执行第一个任务的时候,传入了一个线程池,当执行第二个任务的时候调用的是thenRun方法,则第二个任务和第一个任务是公用同一个线程池。

    • thenRunAsync(Runnable action)
      可以看到它调用没有传入uniRunStage(Executor e, Runnable f) 方法时候Executor参数传的asyncPool,所以它是使用的默认的ForkJoin线程池。
      private static final Executor asyncPool = useCommonPool ? ForkJoinPool.commonPool() : new ThreadPerTaskExecutor();
      也就是说,如果你执行第一个任务的时候,传入了一个线程池,当执行第二个任务的时候调用的是thenRunAsync(Runnable action)方法,则第一个任务使用的是你传入的线程池,第二个任务使用的是ForkJoin线程池,由于ForkJoin线程池是整个应用程序公用的,比如stream使用方法parallel()进行并行运算的时候也是用的ForkJoin线程池,该线程池可以在程序启动的时候进行设置,详情请百度。由于是ForkJoin线程池是公用的,所以,不建议你在不知道程序其他地方哪里还会使用该线程池的情况下使用。

    • thenRunAsync(Runnable action,Executor executor)
      可以看到它调用没有传入uniRunStage(Executor e, Runnable f) 方法时候Executor参数传的是外部传入的自定义线程池,所以它是使用的你指定的线程池。
      也就是说,如果你执行第一个任务的时候,传入了A线程池,当执行第二个任务的时候调用的是thenRunAsync(Runnable action,Executor executor)方法并传入了B线程池,则第一个任务使用的是A线程池,第二个任务使用的是B线程池。

  • 测试代码

package com.finger.fingermall.search.thread;

import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import lombok.extern.slf4j.Slf4j;

/**
 * User: dell Date: 2023/10/28 Time: 10:10 auther: lixh Description: No Description
 */
@Slf4j
public class CompletableFutureTest {

    public static ExecutorService executor = Executors.newFixedThreadPool(10);

    public static void main(String[] args) throws ExecutionException, InterruptedException {
        System.out.println("main....start.......");
        /**
         * 方法执行完成后的处理
         */
        CompletableFuture.supplyAsync(() -> {
            System.out.println("当前线程:" + Thread.currentThread().getId());
            int i = 10 / 2;
//            int i = 10 / 0;
            System.out.println("main运行结果:" + i);
            return i;
        }, executor).thenRun(() -> {
            System.out.println("当前线程:" + Thread.currentThread().getId());
            System.out.println("任务2启动了...");
        });
        System.out.println("main....end.........");
    }

}

  • 运行结果
main....start.......
当前线程:22
main运行结果:5
当前线程:1
任务2启动了...
main....end.........
  • 总结
    无需用到上一步返回结果的时候可以用此方法
4.2 thenAccept方法
  • 方法
public CompletableFuture<Void> thenAccept(Consumer<? super T> action) {
        return uniAcceptStage(null, action);
    }

    public CompletableFuture<Void> thenAcceptAsync(Consumer<? super T> action) {
        return uniAcceptStage(asyncPool, action);
    }

    public CompletableFuture<Void> thenAcceptAsync(Consumer<? super T> action,
                                                   Executor executor) {
        return uniAcceptStage(screenExecutor(executor), action);
    }
  • 测试代码
package com.finger.fingermall.search.thread;

import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import lombok.extern.slf4j.Slf4j;

/**
 * User: dell Date: 2023/10/28 Time: 10:10 auther: lixh Description: No Description
 */
@Slf4j
public class CompletableFutureTest {

    public static ExecutorService executor = Executors.newFixedThreadPool(10);

    public static void main(String[] args) throws ExecutionException, InterruptedException {
        System.out.println("main....start.......");
        /**
         * 方法执行完成后的处理
         */
        CompletableFuture.supplyAsync(() -> {
            System.out.println("当前线程:" + Thread.currentThread().getId());
            int i = 10 / 2;
//            int i = 10 / 0;
            System.out.println("main运行结果:" + i);
            return i;
        }, executor).thenAcceptAsync((res) -> {
            System.out.println("任务2启动了..." + res);
        }, executor);
        System.out.println("main....end.........");
    }

}

  • 运行结果
main....start.......
当前线程:22
main运行结果:5
main....end.........
任务2启动了...5
  • 总结
4.3 thenApply方法
  • 方法
public <U> CompletableFuture<U> thenApply(
        Function<? super T,? extends U> fn) {
        return uniApplyStage(null, fn);
    }

    public <U> CompletableFuture<U> thenApplyAsync(
        Function<? super T,? extends U> fn) {
        return uniApplyStage(asyncPool, fn);
    }

    public <U> CompletableFuture<U> thenApplyAsync(
        Function<? super T,? extends U> fn, Executor executor) {
        return uniApplyStage(screenExecutor(executor), fn);
    }
  • 测试代码
package com.finger.fingermall.search.thread;

import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import lombok.extern.slf4j.Slf4j;

/**
 * User: dell Date: 2023/10/28 Time: 10:10 auther: lixh Description: No Description
 */
@Slf4j
public class CompletableFutureTest {

    public static ExecutorService executor = Executors.newFixedThreadPool(10);

    public static void main(String[] args) throws ExecutionException, InterruptedException {
        System.out.println("main....start.......");
        /**
         * 方法执行完成后的处理
         */
        CompletableFuture<String> future = CompletableFuture.supplyAsync(() -> {
            System.out.println("当前线程:" + Thread.currentThread().getId());
            int i = 10 / 2;
//            int i = 10 / 0;
            System.out.println("main运行结果:" + i);
            return i;
        }, executor).thenApplyAsync((res) -> {
            System.out.println("任务2启动了..." + res);
            return "Hello" + res;
        }, executor);
        System.out.println("main....end........."+future.get());
    }

}
  • 运行结果
main....start.......
当前线程:22
main运行结果:5
任务2启动了...5
main....end.........Hello5
  • 总结

5. 两任务组合

5.1 runAfterBoth方法
  • 方法
public CompletableFuture<Void> runAfterBoth(CompletionStage<?> other,
                                                Runnable action) {
        return biRunStage(null, other, action);
    }

    public CompletableFuture<Void> runAfterBothAsync(CompletionStage<?> other,
                                                     Runnable action) {
        return biRunStage(asyncPool, other, action);
    }

    public CompletableFuture<Void> runAfterBothAsync(CompletionStage<?> other,
                                                     Runnable action,
                                                     Executor executor) {
        return biRunStage(screenExecutor(executor), other, action);
    }
  • 测试代码
package com.finger.fingermall.search.thread;

import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import lombok.extern.slf4j.Slf4j;

/**
 * User: dell Date: 2023/10/28 Time: 10:10 auther: lixh Description: No Description
 */
@Slf4j
public class CompletableFutureTest {

    public static ExecutorService executor = Executors.newFixedThreadPool(10);

    public static void main(String[] args) throws ExecutionException, InterruptedException {
        System.out.println("main....start.......");
        /**
         * 方法执行完成后的处理
         */
        CompletableFuture<Object> future01 = CompletableFuture.supplyAsync(() -> {
            System.out.println("任务1线程:" + Thread.currentThread().getId());
            int i = 10 / 4;
//            int i = 10 / 0;
            System.out.println("任务1结束");
            return i;
        }, executor);

        CompletableFuture<Object> future02 = CompletableFuture.supplyAsync(() -> {
            System.out.println("任务2线程:" + Thread.currentThread().getId());
            try {
                Thread.sleep(3000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println("任务2结束");
            return "Hello";
        }, executor);

        future01.runAfterBothAsync(future02, () -> {
            System.out.println("任务3开始...");
//            log.info("任务3开始...任务1结果:{}, 任务2结果:{}", res1, res2);
        }, executor);

        System.out.println("main....end........."+future01.get());
    }

}

  • 运行结果
main....start.......
任务1线程:22
任务1结束
任务2线程:23
main....end.........2
任务2结束
任务3开始...
  • 总结
5.2 thenAcceptBoth方法
  • 方法
public <U> CompletableFuture<Void> thenAcceptBoth(
        CompletionStage<? extends U> other,
        BiConsumer<? super T, ? super U> action) {
        return biAcceptStage(null, other, action);
    }

    public <U> CompletableFuture<Void> thenAcceptBothAsync(
        CompletionStage<? extends U> other,
        BiConsumer<? super T, ? super U> action) {
        return biAcceptStage(asyncPool, other, action);
    }

    public <U> CompletableFuture<Void> thenAcceptBothAsync(
        CompletionStage<? extends U> other,
        BiConsumer<? super T, ? super U> action, Executor executor) {
        return biAcceptStage(screenExecutor(executor), other, action);
    }
  • 测试代码
package com.finger.fingermall.search.thread;

import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import lombok.extern.slf4j.Slf4j;

/**
 * User: dell Date: 2023/10/28 Time: 10:10 auther: lixh Description: No Description
 */
@Slf4j
public class CompletableFutureTest {

    public static ExecutorService executor = Executors.newFixedThreadPool(10);

    public static void main(String[] args) throws ExecutionException, InterruptedException {
        System.out.println("main....start.......");
        /**
         * 方法执行完成后的处理
         */
        CompletableFuture<Object> future01 = CompletableFuture.supplyAsync(() -> {
            System.out.println("任务1线程:" + Thread.currentThread().getId());
            int i = 10 / 4;
//            int i = 10 / 0;
            System.out.println("任务1结束");
            return i;
        }, executor);

        CompletableFuture<Object> future02 = CompletableFuture.supplyAsync(() -> {
            System.out.println("任务2线程:" + Thread.currentThread().getId());
            try {
                Thread.sleep(3000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println("任务2结束");
            return "Hello";
        }, executor);

        future01.thenAcceptBothAsync(future02, (res1, res2) -> {
            System.out.println("任务3开始...");
            log.info("任务3开始...任务1结果:{}, 任务2结果:{}", res1, res2);
        }, executor);

        System.out.println("main....end........."+future01.get());
    }

}

  • 运行结果
main....start.......
任务1线程:22
任务1结束
任务2线程:23
main....end.........2
任务2结束
任务3开始...
11:10:20.300 [pool-1-thread-3] INFO com.finger.fingermall.search.thread.CompletableFutureTest - 任务3开始...任务1结果:2, 任务2结果:Hello
  • 总结
    组合两个future,获取两个future任务的返回结果,然后处理任务,没有返回值
5.3 thenCombine方法
  • 方法
public <U,V> CompletableFuture<V> thenCombine(
        CompletionStage<? extends U> other,
        BiFunction<? super T,? super U,? extends V> fn) {
        return biApplyStage(null, other, fn);
    }

    public <U,V> CompletableFuture<V> thenCombineAsync(
        CompletionStage<? extends U> other,
        BiFunction<? super T,? super U,? extends V> fn) {
        return biApplyStage(asyncPool, other, fn);
    }

    public <U,V> CompletableFuture<V> thenCombineAsync(
        CompletionStage<? extends U> other,
        BiFunction<? super T,? super U,? extends V> fn, Executor executor) {
        return biApplyStage(screenExecutor(executor), other, fn);
    }
  • 测试代码
package com.finger.fingermall.search.thread;

import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import lombok.extern.slf4j.Slf4j;

/**
 * User: dell Date: 2023/10/28 Time: 10:10 auther: lixh Description: No Description
 */
@Slf4j
public class CompletableFutureTest {

    public static ExecutorService executor = Executors.newFixedThreadPool(10);

    public static void main(String[] args) throws ExecutionException, InterruptedException {
        System.out.println("main....start.......");
        /**
         * 方法执行完成后的处理
         */
        CompletableFuture<Object> future01 = CompletableFuture.supplyAsync(() -> {
            System.out.println("任务1线程:" + Thread.currentThread().getId());
            int i = 10 / 4;
//            int i = 10 / 0;
            System.out.println("任务1结束");
            return i;
        }, executor);

        CompletableFuture<Object> future02 = CompletableFuture.supplyAsync(() -> {
            System.out.println("任务2线程:" + Thread.currentThread().getId());
            try {
                Thread.sleep(3000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println("任务2结束");
            return "Hello";
        }, executor);

        CompletableFuture<String> future03 = future01.thenCombineAsync(future02, (res1, res2) -> {
            System.out.println("任务3开始...");
            log.info("任务3开始...任务1结果:{}, 任务2结果:{}", res1, res2);
            return res1 + ":" + res2 + " -> Haha";
        }, executor);

        System.out.println("main....end........."+future03.get());
    }

}

  • 运行结果
main....start.......
任务1线程:22
任务1结束
任务2线程:23
任务2结束
任务3开始...
11:23:10.605 [pool-1-thread-3] INFO com.finger.fingermall.search.thread.CompletableFutureTest - 任务3开始...任务1结果:2, 任务2结果:Hello
main....end.........2:Hello -> Haha
  • 总结
    组合两个future,获取两个future的返回结果,并返回当前任务的返回值

6. 两任务组合–一个完成

6.1 runAfterEither方法
  • 方法
public CompletableFuture<Void> runAfterEither(CompletionStage<?> other,
                                                  Runnable action) {
        return orRunStage(null, other, action);
    }

    public CompletableFuture<Void> runAfterEitherAsync(CompletionStage<?> other,
                                                       Runnable action) {
        return orRunStage(asyncPool, other, action);
    }

    public CompletableFuture<Void> runAfterEitherAsync(CompletionStage<?> other,
                                                       Runnable action,
                                                       Executor executor) {
        return orRunStage(screenExecutor(executor), other, action);
    }
  • 测试代码
package com.finger.fingermall.search.thread;

import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import lombok.extern.slf4j.Slf4j;

/**
 * User: dell Date: 2023/10/28 Time: 10:10 auther: lixh Description: No Description
 */
@Slf4j
public class CompletableFutureTest {

    public static ExecutorService executor = Executors.newFixedThreadPool(10);

    public static void main(String[] args) throws ExecutionException, InterruptedException {
        System.out.println("main....start.......");
        /**
         * 方法执行完成后的处理
         */
        CompletableFuture<Object> future01 = CompletableFuture.supplyAsync(() -> {
            System.out.println("任务1线程:" + Thread.currentThread().getId());
            int i = 10 / 4;
//            int i = 10 / 0;
            System.out.println("任务1结束");
            return i;
        }, executor);

        CompletableFuture<Object> future02 = CompletableFuture.supplyAsync(() -> {
            System.out.println("任务2线程:" + Thread.currentThread().getId());
            try {
                Thread.sleep(3000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println("任务2结束");
            return "Hello";
        }, executor);

        future01.runAfterEitherAsync(future02, () -> {
            System.out.println("任务3开始...");
//            log.info("任务3开始...任务1结果:{}, 任务2结果:{}", res1, res2);
//            return res + ":" + " -> Haha";
        }, executor);

        System.out.println("main....end.........");
    }

}

  • 运行结果
main....start.......
任务1线程:22
任务1结束
任务2线程:23
main....end.........
任务3开始...
任务2结束
  • 总结
    组合两个future,不需要获取future的结果,只需两个future处理完任务后,处理该任务
6.2 acceptEither方法
  • 方法
public CompletableFuture<Void> acceptEither(
        CompletionStage<? extends T> other, Consumer<? super T> action) {
        return orAcceptStage(null, other, action);
    }

    public CompletableFuture<Void> acceptEitherAsync(
        CompletionStage<? extends T> other, Consumer<? super T> action) {
        return orAcceptStage(asyncPool, other, action);
    }

    public CompletableFuture<Void> acceptEitherAsync(
        CompletionStage<? extends T> other, Consumer<? super T> action,
        Executor executor) {
        return orAcceptStage(screenExecutor(executor), other, action);
    }
  • 测试代码
package com.finger.fingermall.search.thread;

import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import lombok.extern.slf4j.Slf4j;

/**
 * User: dell Date: 2023/10/28 Time: 10:10 auther: lixh Description: No Description
 */
@Slf4j
public class CompletableFutureTest {

    public static ExecutorService executor = Executors.newFixedThreadPool(10);

    public static void main(String[] args) throws ExecutionException, InterruptedException {
        System.out.println("main....start.......");
        /**
         * 方法执行完成后的处理
         */
        CompletableFuture<Object> future01 = CompletableFuture.supplyAsync(() -> {
            System.out.println("任务1线程:" + Thread.currentThread().getId());
            int i = 10 / 4;
//            int i = 10 / 0;
            System.out.println("任务1结束");
            return i;
        }, executor);

        CompletableFuture<Object> future02 = CompletableFuture.supplyAsync(() -> {
            System.out.println("任务2线程:" + Thread.currentThread().getId());
            try {
                Thread.sleep(3000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println("任务2结束");
            return "Hello";
        }, executor);

        future01.acceptEitherAsync(future02, (res) -> {
            System.out.println("任务3开始...");
//            log.info("任务3开始...任务1结果:{}, 任务2结果:{}", res1, res2);
//            return res + ":" + " -> Haha";
        }, executor);

        System.out.println("main....end.........");
    }

}

  • 运行结果
main....start.......
任务1线程:22
任务1结束
任务2线程:23
main....end.........
任务3开始...
任务2结束
  • 总结
    组合两个future,不需要获取future的结果,只需两个future处理完成任务后,处理该任务
6.3 applyToEither方法
  • 方法
public <U> CompletableFuture<U> applyToEither(
        CompletionStage<? extends T> other, Function<? super T, U> fn) {
        return orApplyStage(null, other, fn);
    }

    public <U> CompletableFuture<U> applyToEitherAsync(
        CompletionStage<? extends T> other, Function<? super T, U> fn) {
        return orApplyStage(asyncPool, other, fn);
    }

    public <U> CompletableFuture<U> applyToEitherAsync(
        CompletionStage<? extends T> other, Function<? super T, U> fn,
        Executor executor) {
        return orApplyStage(screenExecutor(executor), other, fn);
    }
  • 测试代码
package com.finger.fingermall.search.thread;

import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import lombok.extern.slf4j.Slf4j;

/**
 * User: dell Date: 2023/10/28 Time: 10:10 auther: lixh Description: No Description
 */
@Slf4j
public class CompletableFutureTest {

    public static ExecutorService executor = Executors.newFixedThreadPool(10);

    public static void main(String[] args) throws ExecutionException, InterruptedException {
        System.out.println("main....start.......");
        /**
         * 方法执行完成后的处理
         */
        CompletableFuture<Object> future01 = CompletableFuture.supplyAsync(() -> {
            System.out.println("任务1线程:" + Thread.currentThread().getId());
            int i = 10 / 4;
//            int i = 10 / 0;
            System.out.println("任务1结束");
            return i;
        }, executor);

        CompletableFuture<Object> future02 = CompletableFuture.supplyAsync(() -> {
            System.out.println("任务2线程:" + Thread.currentThread().getId());
            try {
                Thread.sleep(3000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println("任务2结束");
            return "Hello";
        }, executor);

        CompletableFuture<String> future03 = future01.applyToEitherAsync(future02, (res) -> {
            System.out.println("任务3开始...");
            System.out.println("任务3结束..." + res);
//            log.info("任务3开始...任务1结果:{}, 任务2结果:{}", res1, res2);
            return res + ":" + " -> Haha";
        }, executor);

        System.out.println("main....end........."+future03.get());
    }

}

  • 运行结果
main....start.......
任务1线程:22
任务1结束
任务2线程:23
任务3开始...
任务3结束...2
main....end.........2: -> Haha
任务2结束
  • 总结
    组合两个future,获取两个future的返回结果,并返回当前任务的返回值

7. 多任务组合

4.1 allOf方法
  • 方法
public static CompletableFuture<Void> allOf(CompletableFuture<?>... cfs) {
        return andTree(cfs, 0, cfs.length - 1);
    }
  • 测试代码
package com.finger.fingermall.search.thread;

import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import lombok.extern.slf4j.Slf4j;

/**
 * User: dell Date: 2023/10/28 Time: 10:10 auther: lixh Description: No Description
 */
@Slf4j
public class CompletableFutureTest {

    public static ExecutorService executor = Executors.newFixedThreadPool(10);

    public static void main(String[] args) throws ExecutionException, InterruptedException {
        System.out.println("main....start.......");
        /**
         * 方法执行完成后的处理
         */
        CompletableFuture<Object> futureImg = CompletableFuture.supplyAsync(() -> {
            System.out.println("查询商品的图片信息");
            return "Hello.jpg";
        }, executor);

        CompletableFuture<Object> futureAttr = CompletableFuture.supplyAsync(() -> {
            try {
                Thread.sleep(3000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println("查询商品的属性");
            return "黑色+256G";
        }, executor);

        CompletableFuture<Object> futureDesc = CompletableFuture.supplyAsync(() -> {
            System.out.println("查询商品的介绍");
            return "华为";
        }, executor);

        //等待所有结果完成
        CompletableFuture.allOf(futureImg, futureAttr, futureDesc).get();

        System.out.println("main....end.........");
    }

}

  • 运行结果
main....start.......
查询商品的图片信息
查询商品的介绍
查询商品的属性
main....end.........
  • 总结
    等待所有任务完成
7.2 anyOf方法
  • 方法
public static CompletableFuture<Object> anyOf(CompletableFuture<?>... cfs) {
        return orTree(cfs, 0, cfs.length - 1);
    }
  • 测试代码
package com.finger.fingermall.search.thread;

import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import lombok.extern.slf4j.Slf4j;

/**
 * User: dell Date: 2023/10/28 Time: 10:10 auther: lixh Description: No Description
 */
@Slf4j
public class CompletableFutureTest {

    public static ExecutorService executor = Executors.newFixedThreadPool(10);

    public static void main(String[] args) throws ExecutionException, InterruptedException {
        System.out.println("main....start.......");
        /**
         * 方法执行完成后的处理
         */
        CompletableFuture<Object> futureImg = CompletableFuture.supplyAsync(() -> {
            System.out.println("查询商品的图片信息");
            return "Hello.jpg";
        }, executor);

        CompletableFuture<Object> futureAttr = CompletableFuture.supplyAsync(() -> {
            try {
                Thread.sleep(3000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println("查询商品的属性");
            return "黑色+256G";
        }, executor);

        CompletableFuture<Object> futureDesc = CompletableFuture.supplyAsync(() -> {
            System.out.println("查询商品的介绍");
            return "华为";
        }, executor);

        //等待所有结果完成
        CompletableFuture.anyOf(futureImg, futureAttr, futureDesc).get();

        System.out.println("main....end.........");
    }

}

  • 运行结果
main....start.......
查询商品的图片信息
main....end.........
查询商品的介绍
查询商品的属性
  • 总结
    等待所有任务完成
    只要有一个任务完成
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值