如何杀死CompletableFuture相关的主题? [英] How to kill CompletableFuture related threads?

查看:327
本文介绍了如何杀死CompletableFuture相关的主题?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有检查CompletableFuture执行时间的方法。如果此类CompletableFuture执行的时间超过2秒,我想要终止此任务。但是,如果我没有执行CompletableFuture方法的控制线程,我怎么办?

I have method that is checking the CompletableFuture execution time. If such CompletableFuture is executing for more than 2 seconds i want to kill this task. But how can I doit if i don't have control overy thread where CompletableFuture methods are executed ?

       final CompletableFuture<List<List<Student>>> responseFuture = new CompletableFuture<>();
responseFuture.supplyAsync(this::createAllRandomGroups)
        .thenAccept(this::printGroups)
        .exceptionally(throwable -> {
            throwable.printStackTrace();
            return null;
        });

createAllRandomGroups()

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;
}

printGroups()

printGroups()

private void printGroups(List<List<Student>> lists) {
        System.out.println(lists);

    }

此声明 responseFuture.cancel( true); 不会杀死responseFuture执行方法的线程。那么终止CompletableFuture线程最优雅的方法是什么?

This statement responseFuture.cancel(true); does not kill thread where responseFuture is doing the methods. So what is the most elegant way to terminate CompletableFuture thread ?

推荐答案

创建 CompletableFuture链时阶段如 b = a.thenApply(function),这个方便的方法创建了不同组件的设置。基本上,这些组件互相称为 a→function→b ,因此完成 a 将触发评估函数将首先预先检查 b 是否仍未完成,然后评估您的函数并尝试完成 b 包含结果。

When you create a chain of CompletableFuture stages like b = a.thenApply(function), this handy method creates a setup of different components. Basically, these components refer to each other as a → function → b, so the completion of a will trigger the evaluation of function which will first pre-check whether b still is not completed, then evaluate your function and attempt to complete b with the result.

但是 b 本身没有了解函数或将评估它的线程。事实上,函数对于 b 并非特殊,任何人都可以调用从任何线程完成 completeExceptionally 取消,第一个获胜。因此,类名中的可完成

But b itself has no knowledge of function or the thread that will evaluate it. In fact, function is not special to b, anyone could call complete, completeExceptionally or cancel on it from any thread, the first one winning. Hence, the completable in the class name.

获得控制线程评估函数的唯一方法是控制它们从一开始就是,例如

The only way to get get hands on the threads evaluating the functions, is to be in control of them right from the start, e.g.

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 ,例如通过取消,将确保此链不会触发新评估,并进一步尝试中断正在进行的评估(如果有)。

Now, the completion of future, e.g. via cancellation, will ensure that no new evaluation will be triggered by this chain and further makes an attempt to interrupt ongoing evaluations, if any.

因此,您可以实施超时,例如

So you can implement a timeout, e.g.

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 已经完成,这是有保证的,因为它的完成会触发关闭。

Not that the rejection of tasks due to the shutdown of the thread pool may cause some of the intermediate future to never complete, but for this chain of stages, this is irrelevant. All that matters, is, that the final stage future is completed, which is guaranteed, as it is its completion which triggers the shutdown.

这篇关于如何杀死CompletableFuture相关的主题?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆