为了账号安全,请及时绑定邮箱和手机立即绑定

在异步执行时停止函数链执行的最佳实践是什么?

在异步执行时停止函数链执行的最佳实践是什么?

三国纷争 2023-08-23 17:20:56
我这里有这个功能:Function<Integer, Integer> func = (value) -> value + 5;        func = func.andThen((value) -> {            //Imagine that here some code executed and raised an exception, I'm throwing it             //manually just for the sake of this example.            throw new RuntimeException("failed");        });        func = func.andThen((value) -> {            System.out.println("Reached last function !");            return value;        });        executeFunction(func);现在,您可以看到我在第一个 andThen 方法中引发了运行时异常。那是因为我想阻止第二个 andThen 被执行。这是最好的方法吗?另外,我注意到,如果我在不同的线程(异步)中执行此函数,则异常不会打印在我的控制台中,并且我想知道异常发生了。private static void executeFunction(Function<Integer, Integer> function) {        CompletableFuture.supplyAsync(() -> function.apply(100));    }在这种情况下,如果我想确保记录异常,但 andThen 链中的下一个函数没有执行,我应该记录并抛出异常吗?这不是一个ati模式吗?
查看完整描述

3 回答

?
慕尼黑8549860

TA贡献1818条经验 获得超11个赞

实例化和抛出大量异常可能会变得相当昂贵,这就是为什么它们应该仅限于特殊情况。相反,您可以使用Optional来控制流:

func = (value) -> Optional.of(value + 5);

func = func.andThen((optionalValue) -> {

    // Instead of throwing an exception, return an empty Optional

    System.out.println("Log the failure");

    return Optional.empty();

});

func = func.andThen((optionalValue) -> {

    optionalValue.map((value) -> { // This lambda will only execute if optionalValue is not empty

        System.out.println("Reached last function !");

        return value; // map wraps this in an Optional

    });

});

// Finally, unwrap the value. Optional provides a number of ways to do this, depending on how you want to handle failure/empty

func = func.andThen((optional) -> optional.orElse(...));

executeFunction(func);


查看完整回答
反对 回复 2023-08-23
?
冉冉说

TA贡献1877条经验 获得超1个赞

您可以为函数/可运行对象编写一个包装器,在任务失败时记录并退出。就像这样:


class Runnables

{

    public static Runnable trying(Runnable... runnables)

    {

        return () ->

        {

            int successes = 0;

            try

            {

                for(Runnable runnable : runnables)

                {

                    runnable.run();

                    successes++;

                }

            }

            catch(Throwable t)

            {

                logger.error("Exception thrown from "+successes+"th runnable: ",t);

            }

        };

    }

}

然后:


private static void executeFunction(Runnable... runnables)

{

    CompletableFuture.supplyAsync(Runnables.trying(runnables));

}


查看完整回答
反对 回复 2023-08-23
?
万千封印

TA贡献1891条经验 获得超3个赞

您可以通过使用CompletableFuture.thenApply方法来获得所需的行为。例如:

public class Answer {

  public static void main(String[] args) {

    Function<Integer, Integer> fn0 = v -> v + 5;


    Function<Integer, Integer> fn1 = v -> {

        throw new RuntimeException("failed");

    };


    Function<Integer, Integer> fn2 = v -> {

        System.out.println("Reached last function !");

        return v;

    };


    CompletableFuture.supplyAsync(() -> fn0.apply(100))

            .thenApply(fn1)

            .thenApply(fn2)

            .exceptionally(throwable -> {

                // next line prints the exception thrown by fn1, wrapped in java.util.concurrent.CompletionException

                System.out.println("Failed with error: " + throwable); 

                return 0; // default value, used when exception is thrown

            });

  }

}

基本上,CompletableFuture链将被“开箱即用”的异常中断,因此不需要额外的处理。


或者,如果您想要更通用的方法:


public class Answer {

  public static void main(String[] args) {

    executeAsync(() -> stepOne(100))

            .thenApply(Answer::stepTwo)

            .thenApply(Answer::finalStep)

            .exceptionally(Answer::handleException);

  }


  private static CompletableFuture<Integer> executeAsync(Supplier<Integer> task) {

    return CompletableFuture.supplyAsync(task::get);

  }


  private static Integer stepOne(Integer value) {

    return value + 5;

  }


  private static Integer stepTwo(Integer value) {

    throw new RuntimeException("failed");

  }


  private static Integer finalStep(Integer value) {

    System.out.println("Reached last function !");

    return value;

  }


  private static Integer handleException(Throwable throwable) {

    // next line prints the exception thrown by any step before, wrapped in java.util.concurrent.CompletionException

    System.out.println("Failed with error: " + throwable);

    return 0; // default value

  }

笔记:


使用thenApply您可以根据需要链接任意数量的函数调用


在最后一个示例中,同一类中的方法可以替换为其他类中的方法(不一定是静态类)


查看完整回答
反对 回复 2023-08-23
  • 3 回答
  • 0 关注
  • 162 浏览

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信