我无法为需要协调不同任务的程序实现优雅的功能样式解决方案。这就是我想要实现的目标。
我有三个类我想要编排的方法(简化为简洁):
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
&#39; n&#39;并行时间和TaskA
的每次执行,我需要执行TaskB
&#39; n&#39;使用相应TaskA
的结果的时间。最后,我需要使用TaskC
的所有调用的结果执行TaskB
。
实现这一目标的一种方法是创建一个Callable
来封装对TaskA
和TaskB
的调用,最后在我的主线程中,收集List
的{要Future
执行ResultB
的{1}} {/ p>}
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
这样的Java并发库类来摆脱它。
任何指针?
答案 0 :(得分:0)
我找到了一种使用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());
}
答案 1 :(得分:-1)
我认为CompletableFuture确实会证明最优雅:
int taskCount = 100;
List<ResultB> resultBs = IntStream.range(0, taskCount)
.mapToObj(i -> new TaskA())
.map(taskA -> CompletableFuture.supplyAsync(taskA::call))
.map(completableFutureA -> completableFutureA.thenApplyAsync(new TaskB()::call))
.collect(Collectors.toList()) // collect, in order to kick off the async tasks
.stream()
.map(CompletableFuture::join)
.collect(Collectors.toList());
return new TaskC().call(resultBs);