Encodera

Спасибо, что читаете!

Пожертвуйте сайту, мы стараемся ради вас.

Как ограничить время выполнения задачи

Короткий ответ

Future.get() с тайм-аутом ждёт не дольше указанного времени и выбрасывает TimeoutException:

void main() throws Exception {
    try (var pool = Executors.newSingleThreadExecutor()) {
        Future<String> future = pool.submit(() -> {
            Thread.sleep(2000);
            return "report";
        });
        try {
            IO.println(future.get(300, TimeUnit.MILLISECONDS));
        } catch (TimeoutException e) {
            future.cancel(true);
            IO.println("Too slow, cancelled: " + future.isCancelled());
        }
    }
}

Результат:

Too slow, cancelled: true

cancel(true) прерывает поток задачи, иначе пул ждал бы её завершения при закрытии.

Значение по умолчанию

completeOnTimeout() подставляет значение, если задача не успела:

void main() {
    String result = CompletableFuture.supplyAsync(() -> {
                try {
                    Thread.sleep(1000);
                } catch (InterruptedException e) {
                    Thread.currentThread().interrupt();
                }
                return "fresh data";
            })
            .completeOnTimeout("cached data", 200, TimeUnit.MILLISECONDS)
            .join();
    IO.println(result);
}

Результат:

cached data

Ошибка по тайм-ауту

orTimeout() завершает задачу с TimeoutException:

void main() {
    var future = CompletableFuture.supplyAsync(() -> {
        try {
            Thread.sleep(1000);
        } catch (InterruptedException e) {
            Thread.currentThread().interrupt();
        }
        return 42;
    }).orTimeout(200, TimeUnit.MILLISECONDS);
 
    try {
        future.join();
    } catch (CompletionException e) {
        IO.println(e.getCause().getClass().getSimpleName());
    }
}

Результат:

TimeoutException

Частая ошибка

Вызывать get() без тайм-аута для задач, которые ходят в сеть. Если сервер не ответит, программа будет ждать вечно. Ставьте ограничение и на саму операцию (например, тайм-аут у HTTP-клиента), и на ожидание результата.

Функции из этого ответа

  • Future.get() — Ждёт завершения задачи и возвращает её результат.
  • CompletableFuture.supplyAsync() — Запускает вычисление асинхронно и возвращает `CompletableFuture`.

Спасибо, что читаете!

Пожертвуйте сайту, мы стараемся ради вас.