我有检查 CompletableFuture 执行时间的方法。如果这样的 CompletableFuture 执行时间超过 2 秒,我想终止此任务。但是,如果我无法控制执行 CompletableFuture 方法的线程,我该怎么办?
final CompletableFuture<List<List<Student>>> responseFuture = new CompletableFuture<>();
responseFuture.supplyAsync(this::createAllRandomGroups)
.thenAccept(this::printGroups)
.exceptionally(throwable -> {
throwable.printStackTrace();
return null;
});
createAllRandomGroups()
private List<List<Student>> createAllRandomGroups() {
System.out.println("XD");
List<Student> allStudents = ClassGroupUtils.getActiveUsers();
Controller controller = Controller.getInstance();
List<List<Student>> groups = new ArrayList<>();
int groupSize = Integer.valueOf(controller.getGroupSizeComboBox().getSelectionModel().getSelectedItem());
int numberOfGroupsToGenerate = allStudents.size() / groupSize;
int studentWithoutGroup = allStudents.size() % groupSize;
if (studentWithoutGroup != 0) groups.add(this.getListOfStudentsWithoutGroup(allStudents, groupSize));
for(int i = 0; i < numberOfGroupsToGenerate; i++) {
boolean isGroupCreated = false;
while (!isGroupCreated){
Collections.shuffle(allStudents);
List<Student> newGroup = this.createNewRandomGroupOfStudents(allStudents, groupSize);
groups.add(newGroup);
if (!DataManager.isNewGroupDuplicated(newGroup.toString())) {
isGroupCreated = true;
allStudents.removeAll(newGroup);
}
}
}
DataManager.saveGroupsToCache(groups);
return groups;
}
打印组()
private void printGroups(List<List<Student>> lists) {
System.out.println(lists);
}
此语句 responseFuture.cancel(true);
不会终止 responseFuture 正在执行方法的线程。那么终止 CompletableFuture 线程最优雅的方法是什么?
最佳答案
当您创建一系列 CompletableFuture
阶段(例如 b = a.thenApply(function)
)时,这个方便的方法会创建不同组件的设置。基本上,这些组件相互引用为 a → function → b
,因此 a
的完成将触发对 function
的求值,它首先会预先检查 b
是否仍未完成,然后评估您的函数并尝试使用结果完成 b
。
但是 b
本身不知道 function
或将计算它的线程。事实上,function
对b
来说并不特殊,任何人 都可以调用complete
,completeExceptionally
或 取消
从任何线程,第一个获胜。因此,类名中的 completable。
接触评估函数的线程的唯一方法是从一开始就控制它们,例如
ExecutorService myWorkers = Executors.newFixedThreadPool(2);
CompletableFuture<FinalResultType> future
= CompletableFuture.supplyAsync(() -> generateInitialValue(), myWorkers)
.thenApplyAsync(v -> nextCalculation(v), myWorkers)
.thenApplyAsync(v -> lastCalculation(v), myWorkers);
future.whenComplete((x,y) -> myWorkers.shutdownNow());
现在,完成future
,例如通过取消,将确保该链不会触发新的评估,并进一步尝试中断正在进行的评估(如果有的话)。
所以你可以实现超时,例如
try {
try {
FinalResultType result = future.get(2, TimeUnit.SECONDS);
System.out.println("got "+result);
}
catch(TimeoutException ex) {
if(future.cancel(true)) System.out.println("cancelled");
else System.out.println("got "+future.get());
}
}
catch(ExecutionException|InterruptedException ex) {
ex.printStackTrace();
}
并不是说由于线程池的关闭而导致的任务拒绝可能会导致一些中间的 future 永远无法完成,但对于这个阶段链来说,这是无关紧要的。重要的是,最后阶段 future
已经完成,这是有保证的,因为它的完成会触发关闭。
关于java - 如何杀死 CompletableFuture 相关线程?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/47597798/