CompletableFuture<T> 的正确打开方式

CompletableFuture 的正确打开方式

1. runAsync 和 supplyAsync 方法

CompletableFuture提供了四个静态方法

public static CompletableFuture<Void> runAsync(Runnable runnable)

public static CompletableFuture<Void> runAsync(Runnable runnable, Executor executor)

public static <U> CompletableFuture<U> supplyAsync(Supplier<U> supplier)

public static <U> CompletableFuture<U> supplyAsync(Supplier<U> supplier, Executor executor)

该四个方法可以用来创建CompletableFuture对象,当不传入Executor时使用默认的ForkJoinPool.commonPool()作为它的线程池执行异步代码,如果指定了线程池,则使用指定的线程池运行线程。

  • runAsync 不支持返回值

  • supplyAsync 支持返回值

代码示例如下:

// 无返回值函数示例
public static void runAsync() throws Exception {
  CompletableFuture<Void> future = CompletableFuture.runAsync(() -> {
    try {
      TimeUnit.SECONDS.sleep(3);
    } catch (InterruptedException e) {
      logger.error("线程被打断: " + e);
    }
    logger.info("线程执行完成!");
  });

  future.get();
}


// 有返回值函数示例
public static void supplyAsync() throws Exception {
  CompletableFuture<Long> future = CompletableFuture.supplyAsync(() -> {
    try {
      TimeUnit.SECONDS.sleep(1);
    } catch (InterruptedException e) {
      logger.error("线程被打断: " + e);
    }
    logger.info("线程执行完成!");
    return System.currentTimeMillis();
  });

  long time = future.get();

  logger.info("完成时间: " + time);
}

2. 计算结果完成或者异常时的回调方法

CompletableFuture的计算完成或者抛出异常时,可以执行特定的Action操作,由以下函数定义

public CompletableFuture<T> whenComplete(BiConsumer<? super T, ? super Throwable> action)

public CompletableFuture<T> whenCompleteAsync(BiConsumer<? super T, ? super Throwable> action)

public CompletableFuture<T> whenCompleteAsync(BiConsumer<? super T, ? super Throwable> action, Executor executor)

public CompletableFuture<T> exceptionally(Function<Throwable, ? extends T> fn)

  • whenComplete 使用执行当前任务的线程继续执行whenCompleteAction任务.

  • whenCompleteAsyncAction任务提交给线程池来执行,当不指定线程池时使用默认的ForkJoinPool.commonPool()线程池.

  • exceptionally 当执行任务出现异常时执行该方法定义的Action.

代码示例如下:

CompletableFuture<Void> future1 = CompletableFuture.runAsync(() -> {
  try {
    TimeUnit.SECONDS.sleep(3);
  } catch (InterruptedException e) {
  }
  if (new Random().nextInt() % 2 >= 0) {
    int i = 1 / 0;
  }
  logger.info("线程执行完成!");
});
// 线程执行完成
future1.whenComplete((t, action) -> logger.info("执行完成!"));
// 线程出现异常
future1.exceptionally(t -> {
  logger.warn("执行失败: {}", t.getMessage());
  return null;
});

3. 线程串行化

当一个线程依赖另一个线程时,可以使用thenApply方法来把这两个线程串行化,CompletableFuture提供了如下三个方法

public <U> CompletableFuture<U> thenApply(Function<? super T,? extends U> fn)

public <U> CompletableFuture<U> thenApplyAsync(Function<? super T,? extends U> fn)

public <U> CompletableFuture<U> thenApplyAsync(Function<? super T,? extends U> fn, Executor executor)

范型T为上一个任务返回结果的类型,U为当前任务的返回类型

代码示例如下:

CompletableFuture<Integer> future2 = CompletableFuture.supplyAsync(() -> {
  Integer result = new Random().nextInt(100);
  logger.info("result1: {}", result);
  return result;
}).thenApply(t -> {
  Integer result = t * 5;
  logger.info("result2: {}", result);
  return result;
});

long result = future2.get();
logger.info("最终结果: {}", result);

该示例中第二个任务依赖第一个任务的结果

4. 任务执行完成的处理器

handle是执行任务完成时对结果的处理。和thenApply方法处理方式基本一样。不同的是handle是在任务完成后再执行,还可以处理异常的任务。thenApply只可以执行正常的任务,任务出现异常则不执行thenApply方法。CompletableFuture提供了如下三个方法

public <U> CompletionStage<U> handle(BiFunction<? super T, Throwable, ? extends U> fn)

public <U> CompletionStage<U> handleAsync(BiFunction<? super T, Throwable, ? extends U> fn)

public <U> CompletionStage<U> handleAsync(BiFunction<? super T, Throwable, ? extends U> fn,Executor executor)

代码示例如下:

CompletableFuture<Integer> future = CompletableFuture.supplyAsync(() -> {
  int i = 1 / 0;
  return new Random().nextInt(10);
}).handle((param, throwable) -> {
  int result = -1;
  if (throwable == null) {
    result = param * 2;
  } else {
    logger.warn(throwable.getMessage());
  }
  return result;
});
logger.info("result: {}", future.get());

handle中可以根据任务是否有异常来进行做相应的后续处理操作

5. 结果处理方法

thenAccept方法进行结果处理,无返回值,CompletableFuture提供了如下三个方法

public CompletionStage<Void> thenAccept(Consumer<? super T> action)

public CompletionStage<Void> thenAcceptAsync(Consumer<? super T> action)

public CompletionStage<Void> thenAcceptAsync(Consumer<? super T> action,Executor executor)

代码示例如下:

CompletableFuture<Void> future = CompletableFuture
  .supplyAsync(() -> new Random().nextInt(10))
  .thenAccept(integer -> logger.info("消费结果: {}", integer));
future.get();

该方法没有后续输出操作

6. thenRun 方法使用

thenRun不关心任务的处理结果。只要上面的任务执行完成,就开始执行,CompletableFuture提供了如下三个方法

public CompletionStage<Void> thenRun(Runnable action)

public CompletionStage<Void> thenRunAsync(Runnable action)

public CompletionStage<Void> thenRunAsync(Runnable action,Executor executor)

代码示例如下:

CompletableFuture<Void> future = CompletableFuture
  .supplyAsync(() -> new Random().nextInt(10))
  .thenRun(() -> logger.info("执行 thenRun 方法"));
future.get();

7. 任务合并

thenCombine会把两个CompletionStage的任务都执行完成后,把两个任务的结果一块交给thenCombine来处理,CompletableFuture提供了如下三个方法

public <U,V> CompletionStage<V> thenCombine(CompletionStage<? extends U> other,BiFunction<? super T,? super U,? extends V> fn)

public <U,V> CompletionStage<V> thenCombineAsync(CompletionStage<? extends U> other,BiFunction<? super T,? super U,? extends V> fn)

public <U,V> CompletionStage<V> thenCombineAsync(CompletionStage<? extends U> other,BiFunction<? super T,? super U,? extends V> fn,Executor executor)

代码示例如下:

CompletableFuture<Integer> future1 = CompletableFuture.supplyAsync(() -> 123);
CompletableFuture<Integer> future2 = CompletableFuture.supplyAsync(() -> 321);
CompletableFuture<Integer> result = future1.thenCombine(future2, (t, u) -> t + u);
System.out.println(result.get());

8. thenAcceptBoth使用方式

两个CompletionStage都执行完成后,把结果一块交给thenAcceptBoth来进行消耗,CompletableFuture提供了如下三个方法

public <U> CompletionStage<Void> thenAcceptBoth(CompletionStage<? extends U> other,BiConsumer<? super T, ? super U> action)

public <U> CompletionStage<Void> thenAcceptBothAsync(CompletionStage<? extends U> other,BiConsumer<? super T, ? super U> action)

public <U> CompletionStage<Void> thenAcceptBothAsync(CompletionStage<? extends U> other,BiConsumer<? super T, ? super U> action,     Executor executor)

代码示例如下:

CompletableFuture<Integer> f1 = CompletableFuture.supplyAsync(() -> {
  int t = new Random().nextInt(5);
  try {
    TimeUnit.SECONDS.sleep(t);
  } catch (InterruptedException e) {
    e.printStackTrace();
  }
  logger.info("f1: {}", t);
  return t;
});

CompletableFuture<Integer> f2 = CompletableFuture.supplyAsync(() -> {
  int t = new Random().nextInt(5);
  try {
    TimeUnit.SECONDS.sleep(t);
  } catch (InterruptedException e) {
    e.printStackTrace();
  }
  logger.info("f2: {}", t);
  return t;
});

f1.thenAcceptBoth(f2, (t, u) -> logger.info("thenAcceptBoth 结果: [f1: {}, f2: {}]", t, u));

9. applyToEither使用方式

两个CompletionStage,谁执行返回的结果快,我就用那个CompletionStage的结果进行下一步的转化操作,CompletableFuture提供了如下三个方法

public <U> CompletionStage<U> applyToEither(CompletionStage<? extends T> other,Function<? super T, U> fn)

public <U> CompletionStage<U> applyToEitherAsync(CompletionStage<? extends T> other,Function<? super T, U> fn)

public <U> CompletionStage<U> applyToEitherAsync(CompletionStage<? extends T> other,Function<? super T, U> fn,Executor executor)

代码示例如下:

CompletableFuture<Integer> f1 = CompletableFuture.supplyAsync(() -> {
  int t = new Random().nextInt(5);
  try {
    TimeUnit.SECONDS.sleep(t);
  } catch (InterruptedException e) {
    e.printStackTrace();
  }
  logger.info("f1: {}", t);
  return t;
});
CompletableFuture<Integer> f2 = CompletableFuture.supplyAsync(() -> {
  int t = new Random().nextInt(5);
  try {
    TimeUnit.SECONDS.sleep(t);
  } catch (InterruptedException e) {
    e.printStackTrace();
  }
  logger.info("f2: {}", t);
  return t;
});

CompletableFuture<Integer> result = f1.applyToEither(f2, t -> {
  logger.info("t: {}", t);
  return t * 2;
});

logger.info("最后结果: {}", result.get());

10. acceptEither使用方式

两个CompletionStage,谁执行返回的结果快,我就用那个CompletionStage的结果进行下一步的消耗操作,CompletableFuture提供了如下三个方法

public CompletionStage<Void> acceptEither(CompletionStage<? extends T> other,Consumer<? super T> action)

public CompletionStage<Void> acceptEitherAsync(CompletionStage<? extends T> other,Consumer<? super T> action)

public CompletionStage<Void> acceptEitherAsync(CompletionStage<? extends T> other,Consumer<? super T> action,Executor executor)

代码示例如下:

CompletableFuture<Integer> f1 = CompletableFuture.supplyAsync(() -> {
  int t = new Random().nextInt(5);
  try {
    TimeUnit.SECONDS.sleep(t);
  } catch (InterruptedException e) {
    e.printStackTrace();
  }
  logger.info("f1: {}", t);
  return t;
});

CompletableFuture<Integer> f2 = CompletableFuture.supplyAsync(() -> {
  int t = new Random().nextInt(5);
  try {
    TimeUnit.SECONDS.sleep(t);
  } catch (InterruptedException e) {
    e.printStackTrace();
  }
  logger.info("f2: {}", t);
  return t;
});
f1.acceptEither(f2, t -> logger.info("最终结果: {}", t));

11. runAfterEither使用方式

两个CompletionStage,任何一个完成了都会执行下一步的操作(Runnable),CompletableFuture提供了如下三个方法

public CompletionStage<Void> runAfterEither(CompletionStage<?> other,Runnable action)

public CompletionStage<Void> runAfterEitherAsync(CompletionStage<?> other,Runnable action)

public CompletionStage<Void> runAfterEitherAsync(CompletionStage<?> other,Runnable action,Executor executor)

代码示例如下:

CompletableFuture<Integer> f1 = CompletableFuture.supplyAsync(() -> {
  int t = new Random().nextInt(5);
  try {
    TimeUnit.SECONDS.sleep(t);
  } catch (InterruptedException e) {
    e.printStackTrace();
  }
  logger.info("f1: {}", t);
  return t;
});

CompletableFuture<Integer> f2 = CompletableFuture.supplyAsync(() -> {
  int t = new Random().nextInt(5);
  try {
    TimeUnit.SECONDS.sleep(t);
  } catch (InterruptedException e) {
    e.printStackTrace();
  }
  logger.info("f2: {}", t);
  return t;
});
f1.runAfterEither(f2, () -> logger.info("上面有一个已经完成了!"));

12. runAfterBoth使用方式

两个CompletionStage,都完成了计算才会执行下一步的操作(Runnable)

public CompletionStage<Void> runAfterBoth(CompletionStage<?> other,Runnable action)

public CompletionStage<Void> runAfterBothAsync(CompletionStage<?> other,Runnable action)

public CompletionStage<Void> runAfterBothAsync(CompletionStage<?> other,Runnable action,Executor executor)

代码示例如下:

CompletableFuture<Integer> f1 = CompletableFuture.supplyAsync(() -> {
  int t = new Random().nextInt(5);
  try {
    TimeUnit.SECONDS.sleep(t);
  } catch (InterruptedException e) {
    e.printStackTrace();
  }
  logger.info("f1: {}", t);
  return t;
});

CompletableFuture<Integer> f2 = CompletableFuture.supplyAsync(() -> {
  int t = new Random().nextInt(5);
  try {
    TimeUnit.SECONDS.sleep(t);
  } catch (InterruptedException e) {
    e.printStackTrace();
  }
  logger.info("f2: {}", t);
  return t;
});
f1.runAfterBoth(f2, () -> logger.info("上面两个任务都执行完成了!"));

13. thenCompose使用方式

thenCompose 方法允许你对两个 CompletionStage 进行流水线操作,第一个操作完成时,将其结果作为参数传递给第二个操作,CompletableFuture提供了如下三个方法

public <U> CompletableFuture<U> thenCompose(Function<? super T, ? extends CompletionStage<U>> fn)

public <U> CompletableFuture<U> thenComposeAsync(Function<? super T, ? extends CompletionStage<U>> fn)

public <U> CompletableFuture<U> thenComposeAsync(Function<? super T, ? extends CompletionStage<U>> fn, Executor executor)

代码示例如下:

CompletableFuture<Integer> f = CompletableFuture.supplyAsync(() -> {
  int t = new Random().nextInt(5);
  logger.info("t1: {}", t);
  return t;
}).thenCompose(param -> CompletableFuture.supplyAsync(() -> {
  int t = param * 2;
  logger.info("t2: {}", t);
  return t;
}));
logger.info("thenCompose result: {}", f.get());

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值