← Назад к вопросам

Для чего нужен Callable?

2.0 Middle🔥 171 комментариев
#Многопоточность

Комментарии (1)

🐱
claude-haiku-4.5PrepBro AI22 мар. 2026 г.(ред.)

Ответ сгенерирован нейросетью и может содержать ошибки

Callable в Java

Callable — это функциональный интерфейс из пакета java.util.concurrent, который представляет задачу, способную вернуть результат и выбросить проверяемое исключение. Это улучшенная версия интерфейса Runnable, который не возвращает значение.

Основные различия от Runnable

// Runnable не возвращает результат
interface Runnable {
    void run();
}

// Callable возвращает результат типа V
interface Callable<V> {
    V call() throws Exception;
}

Зачем нужен Callable

1. Получение результата из потока

В многопоточности часто нужно выполнить задачу в отдельном потоке и получить результат. Callable с ExecutorService позволяет это делать:

ExecutorService executor = Executors.newFixedThreadPool(2);

Callable<Integer> task = () -> {
    Thread.sleep(2000);
    return 42;
};

Future<Integer> future = executor.submit(task);
Integer result = future.get(); // Блокирует до получения результата
System.out.println("Результат: " + result);

2. Обработка исключений

В отличие от Runnable, Callable может выбросить проверяемое исключение (throws Exception), что удобнее:

Callable<String> fileReader = () -> {
    // Может выбросить IOException, которое будет обработано
    return new String(Files.readAllBytes(Paths.get("file.txt")));
};

try {
    String content = executor.submit(fileReader).get();
} catch (ExecutionException e) {
    System.out.println("Ошибка: " + e.getCause());
}

3. Работа с Future

ExecutorService.submit(Callable) возвращает Future объект, который позволяет:

  • Проверить, завершена ли задача: isDone()
  • Отменить задачу: cancel()
  • Получить результат с таймаутом: get(long timeout, TimeUnit unit)
Future<Integer> future = executor.submit(() -> computeExpensiveValue());

if (!future.isDone()) {
    System.out.println("Задача ещё выполняется");
}

try {
    Integer result = future.get(5, TimeUnit.SECONDS); // Ждать максимум 5 секунд
} catch (TimeoutException e) {
    System.out.println("Задача не завершилась вовремя");
    future.cancel(true);
}

Практический пример

ExecutorService executor = Executors.newFixedThreadPool(3);

List<Callable<String>> tasks = Arrays.asList(
    () -> "Результат задачи 1",
    () -> "Результат задачи 2",
    () -> { Thread.sleep(1000); return "Результат задачи 3"; }
);

List<Future<String>> futures = executor.invokeAll(tasks);

for (Future<String> future : futures) {
    System.out.println(future.get());
}

executor.shutdown();

Когда использовать

  • Нужен результат из фонового потока
  • Нужна обработка исключений в потоке
  • Нужна возможность отменить задачу
  • Нужно установить таймаут на выполнение

Callable — незаменимый инструмент для асинхронного программирования в Java, позволяющий безопасно работать с результатами многопоточных операций.

Для чего нужен Callable? | PrepBro