java – 任务编排实现

我无法为需要协调不同任务的程序实现优雅的功能样式解决方案.这就是我想要实现的目标.

我有三个类我想要编排的方法(简化为简洁):

class TaskA {
    public ResultA call() {
        return new ResultA();
    }
}

class TaskB {
    public ResultB call(ResultA a) {
        return new ResultB();
    }
}

class TaskC {
    public ResultC call(List<ResultB> resultBs) {
        return new ResultC();
    }
}

我需要并行执行TaskA’n’次,并且对于TaskA的每次执行,我需要使用相应TaskA的结果执行TaskB’n’次.最后,我需要使用TaskB的所有调用的结果执行一次TaskC.

实现此目的的一种方法是创建一个Callable,它封装对TaskA和TaskB的调用,最后在我的主线程中,收集ResultB的Futures列表来执行TaskC:

class TaskATaskBCallable implements Callable<ResultB> {
    private TaskA taskA ...;
    private TaskB taskB ...;

    public ResultB call() {
        return taskB.call(taskA.call());
    }
}

在我的主线程中:

private ResultC orchestrate() {
    ExecutorService service = ...;
    List<Callable<ResultB>> callables = ...;

    taskC.call(callables.map(callable -> 
        service.submit(callable)).map(Future::get).collect(Collectors.toList());
}

我不喜欢这个解决方案的一件事是TaskATaskBCallable.这可能是一个不必要的类耦合TaskA和TaskB.而且,如果我必须将另一个任务链接到TaskA和TaskB,我将不得不修改TaskATaskBCallable也可能修改它的名称.我觉得我可以通过更智能地使用像CompletableFuture或Phaser这样的Java并发库类来摆脱它.

有什么指针吗?

最佳答案
我找到了使用CompletableFuture执行此操作的一种方法:

private ResultC orchestrate() {
    ExecutorService service = ...;
    int taskCount = ...;

    List<CompletableFuture<ResultB>> resultBFutures = IntStream.rangeClosed(1, taskCount)
                    .mapToObj((i) -> CompletableFuture.supplyAsync(() -> new TaskA().call(), service))
                    .map(resultAFuture -> resultAFuture.thenApplyAsync(resultA -> new TaskB().call(resultA),
                                    service))
                    .collect(Collectors.toList());

    return new TaskC().call(CompletableFuture.allOf(resultBFutures.toArray(new CompletableFuture[resultBFutures.size()]))
                    .thenApply(v -> resultBFutures.stream().map(CompletableFuture::join)
                                    .collect(Collectors.toList()))
                    .join());
}

转载注明原文:java – 任务编排实现 - 代码日志