Итак, как я могу убить эти асинхронные операции?

я есть метод, который проверяет время выполнения 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;
}

printGroups ()

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

    }

Это утверждениеresponseFuture.cancel(true); не убивает поток, где responseFuture делает методы. Так какой же самый элегантный способ завершить поток CompletableFuture?

 Daniel Pryden01 дек. 2017 г., 20:41
Я что-то не так понял? Похоже, что в этих методах вы вообще не выполняете асинхронную работу. Почему вы используете CompletableFuture вообще?
 masterofdisaster01 дек. 2017 г., 19:00
@DanielPryden Конечно, готово.
 Daniel Pryden01 дек. 2017 г., 18:54
Это зависит от того, какая операция занимает время. Можете ли вы показать код дляcreateAllRandomGroups а такжеprintGroups?
 masterofdisaster01 дек. 2017 г., 18:52
@DanielPryden Так как я могу убить эти операции?
 Daniel Pryden01 дек. 2017 г., 18:27
Вы предполагаете, что есть нить, чтобы убить. Но это выглядит как цепочка асинхронных операций, где, скорее всего, нет потока, ожидающего вообще. Вы не хотите уничтожать поток, вы хотите отменить асинхронную операцию.

Ответы на вопрос(2)

CompletableFuture этапы какb = a.thenApply(function)Этот удобный метод создает настройки различных компонентов. По сути, эти компоненты относятся друг к другу какa → function → bИтак, завершениеa вызовет оценкуfunction который сначала проверит,b еще не завершен, затем оцените свою функцию и попытайтесь завершитьb с результатом.

Ноb сам не знаетfunction или поток, который оценит это. По факту,function не является особенным дляb, кто угодно мог позвонитьcomplete, completeExceptionally или жеcancel на нем из любого потока, первый выиграл. Следовательно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 завершено, что гарантировано, поскольку именно его завершение вызывает отключение.

 Holger04 дек. 2017 г., 10:08
ДляCompletableFuture, отмена - это просто особая форма завершения, поэтому у нее может быть только один из двух возможных результатов: а) она успешно отменена или б) будущее получено другими способами. В любом случае, когдаcancel возвращается, будущее будет завершено. Решение моего ответа отключит исполнителя независимо от того, какое завершение произошло. Затем гарантируется, что никакие новые задачи не могут быть запланированы. Это прервет уже выполняющиеся оценки, которые требуют поддержки прерывания на их стороне, чтобы завершиться раньше; Обойти это невозможно.
 masterofdisaster01 дек. 2017 г., 23:58
Но действительно ли метод отмены, вызванный в будущем после тайм-аута, действительно убивает это будущее, или он просто пытается убить его?

которое является кооперативным механизмом. Это означает, что поток должен реализовать логику прерывания путем обработки исключения InterruptedException.

Но это действительно плохая практика - прерывать потоки, которые вам не принадлежат, что, как мне кажется, ваше дело.

 masterofdisaster01 дек. 2017 г., 18:54
Итак, как я могу убить эти асинхронные операции?

Ваш ответ на вопрос