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

Какой интерфейс нужен для работы с потоками?

1.6 Junior🔥 251 комментариев
#Многопоточность

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

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

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

Интерфейсы для работы с потоками в Java

Поток (Thread) — это наименьшая единица выполнения в Java. Для работы с потоками используется несколько интерфейсов и классов, каждый из которых подходит для разных задач.

Основной интерфейс: Runnable

Runnable — это самый фундаментальный интерфейс для многопоточности.

@FunctionalInterface
public interface Runnable {
    void run();
}

Особенности:

  • Имеет только один метод: run()
  • Не возвращает результат (void)
  • Не выбрасывает checked исключения
  • Functional interface (с Java 8 можно использовать lambda)
// Способ 1: Создать класс, реализующий Runnable
public class MyTask implements Runnable {
    @Override
    public void run() {
        System.out.println("Выполняется в отдельном потоке");
    }
}

// Способ 2: Использовать lambda (Java 8+)
Runnable task = () -> System.out.println("Lambda task");

// Создание и запуск потока
Thread thread = new Thread(task);
thread.start(); // Запустить поток

Интерфейс Callable<T>

Callable — это улучшенная версия Runnable, которая может возвращать результат и выбрасывать исключения.

@FunctionalInterface
public interface Callable<V> {
    V call() throws Exception;
}

Отличия от Runnable:

  • Возвращает результат типа V
  • Может выбросить checked exception
  • Используется с ExecutorService
// Callable с возвращаемым значением
Callable<Integer> task = () -> {
    System.out.println("Выполняется задача");
    return 42;
};

// Запуск через ExecutorService
ExecutorService executor = Executors.newSingleThreadExecutor();
Future<Integer> future = executor.submit(task);

Integer result = future.get(); // Блокирует до получения результата
System.out.println("Результат: " + result); // Выведет 42
executor.shutdown();

Интерфейс Future<V>

Future — это интерфейс для представления результата асинхронного вычисления.

public interface Future<V> {
    boolean cancel(boolean mayInterruptIfRunning);
    boolean isCancelled();
    boolean isDone();
    V get() throws InterruptedException, ExecutionException;
    V get(long timeout, TimeUnit unit) throws InterruptedException, ExecutionException, TimeoutException;
}

Ключевые методы:

  • get() — получить результат (блокирует поток)
  • isDone() — проверить, завершена ли задача
  • cancel() — отменить выполнение
ExecutorService executor = Executors.newSingleThreadExecutor();
Future<String> future = executor.submit(() -> {
    Thread.sleep(1000);
    return "Результат готов";
});

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

String result = future.get(2, TimeUnit.SECONDS); // Ждать max 2 секунды
System.out.println(result);
executor.shutdown();

Интерфейс Executor

Executor — это интерфейс для управления пулом потоков.

public interface Executor {
    void execute(Runnable command);
}

Интерфейс ExecutorService

ExecutorService — это расширение Executor с поддержкой управления жизненным циклом.

public interface ExecutorService extends Executor {
    void shutdown();
    boolean isShutdown();
    boolean isTerminated();
    <T> Future<T> submit(Callable<T> task);
    <T> Future<T> submit(Runnable task, T result);
    Future<?> submit(Runnable task);
    // ... другие методы
}

Примеры использования:

// 1. FixedThreadPool (фиксированное количество потоков)
ExecutorService executor = Executors.newFixedThreadPool(3);
for (int i = 0; i < 10; i++) {
    int taskId = i;
    executor.submit(() -> {
        System.out.println("Task " + taskId + " выполняется потоком " + Thread.currentThread().getName());
    });
}
executor.shutdown();
executor.awaitTermination(10, TimeUnit.SECONDS);

// 2. CachedThreadPool (создаёт потоки по необходимости)
ExecutorService executor = Executors.newCachedThreadPool();

// 3. SingleThreadExecutor (один поток)
ExecutorService executor = Executors.newSingleThreadExecutor();

// 4. ScheduledExecutorService (планирование задач)
ScheduledExecutorService scheduler = Executors.newScheduledThreadPool(1);
scheduler.schedule(() -> System.out.println("Задача"), 5, TimeUnit.SECONDS);
scheduler.scheduleAtFixedRate(() -> System.out.println("Повторяется"), 0, 2, TimeUnit.SECONDS);
scheduler.shutdown();

Сравнение интерфейсов

ИнтерфейсВозвращаемоеИсключенияИспользование
RunnablevoidНет (unchecked только)Thread, Executor
Callable<V>VДа (checked)ExecutorService, Future
Future<V>VДаПолучение результата async задачи
Executor--Управление потоками
ExecutorServiceFuture-Управление пулом потоков

Практический пример: асинхронная обработка данных

public class DataProcessor {
    private ExecutorService executor = Executors.newFixedThreadPool(4);
    
    public Future<String> processDataAsync(String data) {
        return executor.submit(() -> {
            // Долгая операция
            Thread.sleep(2000);
            return "Обработано: " + data;
        });
    }
    
    public void processMultiple(List<String> items) throws ExecutionException, InterruptedException {
        List<Future<String>> futures = items.stream()
            .map(this::processDataAsync)
            .collect(Collectors.toList());
        
        for (Future<String> future : futures) {
            System.out.println(future.get());
        }
    }
    
    public void shutdown() {
        executor.shutdown();
    }
}

Java 21+: Virtual Threads (Project Loom)

// Старый способ (heavy threads)
ExecutorService executor = Executors.newFixedThreadPool(100);

// Java 21+: Virtual Threads (легче, быстрее)
ExecutorService executor = Executors.newVirtualThreadPerTaskExecutor();
for (int i = 0; i < 10000; i++) {
    executor.submit(() -> {
        System.out.println("Virtual thread");
    });
}
executor.shutdown();

Итого

Основные интерфейсы для работы с потоками:

  • Runnable — базовый интерфейс, не возвращает результат
  • Callable<T> — возвращает результат, может выбросить исключение
  • Future<V> — представляет асинхронный результат
  • ExecutorService — управляет пулом потоков

Для современной разработки рекомендуется использовать ExecutorService вместо прямого создания Thread, так как это обеспечивает лучшую производительность и управление ресурсами.

Какой интерфейс нужен для работы с потоками? | PrepBro