java - 如何杀死 CompletableFuture 相关线程?

标签 java multithreading java-8 future completable-future

我有检查 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 或将计算它的线程。事实上,functionb 来说并不特殊,任何人 都可以调用completecompleteExceptionally取消 从任何线程,第一个获胜。因此,类名中的 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/

相关文章:

c - 关闭套接字的问题

java - 为什么原始流没有收集(收集器)?

java - 在 Java 8 中是否有一种简洁的方法来迭代带有索引的流?

serialization - 有没有办法在 Java 8 中使用 Files.lines 读取序列化文件

java - java.util.HashMap 没有在 Kotlin 中实现 java.util.Map 吗?

java - 如何在 GWT 中设置事件边界?

java - 使用 cte 和变量输入优化 SQL 查询

java - JDBC 不会更新 PostgreSQL 数据库

c# - 从 C# 中的后台线程更新 Excel 2003 中的复选框有时会失败

multithreading - future 是否在单个线程上执行? (斯卡拉)