Skip to content

包装器

概述

有些使用场景下偏向于把Chance封装为面向线程池可执行的Callable实例,而Chance天然支持这个特性,简单通过wrap()方法进行包装即可。

使用详解

java
public static void main(String[] args) throws Exception {
    ExecutorService executorService = Executors.newSingleThreadExecutor();
    Chance<String> chance = Chance.<String, Throwable>newBuilder()
            .withNeverRetry()
            .withRecoverIfHasException()
            .withRecovery(attempt -> "Recovery")
            .build();
    Callable<String> c1 = chance.wrap(() -> "Hello");
    Callable<String> c2 = chance.wrap(() -> {
    }, "World");
    Future<String> f1 = executorService.submit(c1);
    Future<String> f2 = executorService.submit(c2);
    System.out.printf("result of f1: %s, result of f2: %s\n", f1.get(), f2.get());
    executorService.shutdown();
    executorService.awaitTermination(1, TimeUnit.SECONDS);
}

上面的代码最终输出结果:

shell
result of f1: Hello, result of f2: World

异常处理

对于使用包装器异步执行的场景,异常处理会有些不同。Future的异常处理会包裹Chance抛出的异常,例如:

java
public static void main(String[] args) throws Exception {
    ExecutorService executorService = Executors.newSingleThreadExecutor();
    Chance<String> chance = Chance.<String, Throwable>newBuilder()
            .withNeverRetry()
            .build();
    Callable<String> c3 = chance.wrap(() -> {
        throw new RuntimeException("Error");
    });
    executorService.submit(c3).get();
}

执行上面的代码会看到类似下面的异常栈:

shell
Exception in thread "main" java.util.concurrent.ExecutionException: cn.vlts.chance.ChanceException:
Retrying calling failed after 1 attempts. Exception message: Error.

想要获取根异常可以考虑使用Chance提供的Utils.U.getRootCause()方法对异常进行提取,从而获取最内层的RuntimeException。采用包装器在非超时或者中断异常的前提下,异常的层次基本如下:

shell
ExecutionException -> ChanceException -> Root Exception

贡献者

页面历史

Released under the MIT License.