Sobes.tech
Назад к вопросам
Junior — Middle
48

Имел ли опыт использования многопоточности в Java проектах?

Компании, где спрашивали
СБЕРСБЕР
DCloud
Драйв Клик
Смарттек
IT OneIT One
СБЕР КорпусСБЕР Корпус

Ответ от нейросети

sobes.tech AI

Что хотят услышать интервьюеры:

Ожидают услышать, что есть практический опыт работы с потоками, синхронизацией и concurrent-коллекциями. Важно показать понимание, зачем многопоточность нужна и какие проблемы она решает. Хорошо, если можно назвать конкретные инструменты Java и типовые риски: race condition, deadlock, contention.

Определение:

Многопоточность в Java — это способ выполнять несколько задач параллельно или конкурентно в рамках одного процесса. Она используется, чтобы повысить отзывчивость приложения, ускорить обработку и лучше использовать ресурсы CPU. На практике это работа с Thread, ExecutorService, Future, synchronized, Lock, ConcurrentHashMap и другими средствами из java.util.concurrent.

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

Типичный пример — обработка нескольких независимых задач одновременно, например загрузка данных из нескольких источников или параллельная обработка файлов.

import java.util.List;
import java.util.concurrent.*;

public class MultiThreadExample {
    public static void main(String[] args) throws InterruptedException, ExecutionException {
        ExecutorService executor = Executors.newFixedThreadPool(3);

        List<Callable<Integer>> tasks = List.of(
            () -> 10,
            () -> 20,
            () -> 30
        );

        List<Future<Integer>> results = executor.invokeAll(tasks);

        int sum = 0;
        for (Future<Integer> result : results) {
            sum += result.get();
        }

        System.out.println("Sum = " + sum);

        executor.shutdown();
    }
}

Пояснение кода:

Код показывает, как запускать несколько задач через пул потоков вместо ручного создания Thread.
Executors.newFixedThreadPool(3) создаёт пул из трёх рабочих потоков.
invokeAll(tasks) отправляет все задачи на выполнение и ждёт завершения каждой.
Через Future.get() получаются результаты, после чего они суммируются.
shutdown() корректно останавливает executor после завершения работы.

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

  • Для обычных задач чаще используют ExecutorService, а не создают Thread вручную.
  • Нужно понимать разницу между параллелизмом и конкурентностью.
  • Важно уметь объяснить проблемы синхронизации: race condition, deadlock, visibility.
  • Для общих данных лучше использовать безопасные concurrent-структуры или корректную синхронизацию.
  • Хороший ответ на собеседовании — это не только “да, использовал”, но и конкретный пример, какие были риски и как они решались.