Ответ
Многопоточность в Java применяется для решения задач, требующих параллельного выполнения, повышения отзывчивости и эффективного использования ресурсов процессора.
Основные сценарии использования:
-
Повышение производительности (Parallel Processing)
- Задача: Обработка больших массивов данных, сложные вычисления (например, рендеринг, математическое моделирование).
- Почему: Распараллеливание на нескольких ядрах CPU сокращает общее время выполнения.
-
Обеспечение отзывчивости (Responsiveness)
- Задача: Графические интерфейсы (UI), серверные приложения.
- Почему: Долгие операции (сетевые запросы, чтение файлов) выполняются в фоновых потоках, не блокируя основной поток, отвечающий за взаимодействие с пользователем или клиентами.
-
Асинхронная обработка и фоновые задачи
- Задача: Логирование, отправка уведомлений, периодическое обновление кэша.
- Почему: Эти задачи не требуют немедленного результата и не должны мешать основному потоку выполнения.
Практический пример с ExecutorService:
import java.util.concurrent.*;
public class ThreadPoolExample {
public static void main(String[] args) {
// Создаем пул из 4 потоков
ExecutorService executor = Executors.newFixedThreadPool(4);
// Отправляем 10 задач на выполнение
for (int i = 0; i < 10; i++) {
int taskId = i;
executor.submit(() -> {
System.out.println("Task " + taskId + " executed by " + Thread.currentThread().getName());
});
}
// Инициируем упорядоченное завершение
executor.shutdown();
try {
// Ожидаем завершения всех задач (но не более 1 минуты)
if (!executor.awaitTermination(1, TimeUnit.MINUTES)) {
executor.shutdownNow(); // Принудительное завершение
}
} catch (InterruptedException e) {
executor.shutdownNow();
}
}
}
⚠️ Критически важное замечание: При работе с общими ресурсами из нескольких потоков необходима синхронизация (ключевое слово synchronized, классы Lock, Atomic-типы) для предотвращения состояний гонки (race condition) и обеспечения корректности данных.