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

Как запустить потоки для решения 10000 задач

2.3 Middle🔥 181 комментариев
#Основы Java

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

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

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

# Параллельное выполнение 10000 задач в Java

1. ExecutorService (рекомендуется)

Используем thread pool для эффективного управления потоками:

import java.util.concurrent.*;

public class TaskProcessor {
    public static void main(String[] args) {
        // Создаём пул потоков (обычно = количеству ядер * 2)
        ExecutorService executor = Executors.newFixedThreadPool(8);
        
        int taskCount = 10000;
        
        for (int i = 0; i < taskCount; i++) {
            final int taskId = i;
            executor.submit(() -> {
                // Выполнение задачи
                processTask(taskId);
            });
        }
        
        // Ожидание завершения всех задач
        executor.shutdown();
        try {
            if (!executor.awaitTermination(1, TimeUnit.HOURS)) {
                executor.shutdownNow(); // Принудительное завершение
            }
        } catch (InterruptedException e) {
            executor.shutdownNow();
            Thread.currentThread().interrupt();
        }
    }
    
    private static void processTask(int taskId) {
        System.out.println("Processing task " + taskId);
        // Логика обработки
    }
}

2. CompletableFuture (современный подход)

import java.util.concurrent.*;
import java.util.stream.IntStream;

public class TaskProcessorModern {
    public static void main(String[] args) {
        ExecutorService executor = Executors.newFixedThreadPool(8);
        
        // Создание и отправка всех задач
        CompletableFuture<?>[] futures = IntStream.range(0, 10000)
            .mapToObj(i -> CompletableFuture.runAsync(() -> {
                processTask(i);
            }, executor))
            .toArray(CompletableFuture[]::new);
        
        // Ожидание завершения всех операций
        try {
            CompletableFuture.allOf(futures).get();
            System.out.println("All tasks completed");
        } catch (InterruptedException | ExecutionException e) {
            Thread.currentThread().interrupt();
            e.printStackTrace();
        } finally {
            executor.shutdown();
        }
    }
    
    private static void processTask(int taskId) {
        // Логика выполнения
    }
}

3. ForkJoinPool (для рекурсивных задач)

import java.util.concurrent.RecursiveTask;
import java.util.concurrent.ForkJoinPool;

public class ParallelTaskProcessor extends RecursiveTask<Integer> {
    private static final int THRESHOLD = 100; // Порог разбиения
    private int[] tasks;
    private int start, end;
    
    public ParallelTaskProcessor(int[] tasks, int start, int end) {
        this.tasks = tasks;
        this.start = start;
        this.end = end;
    }
    
    @Override
    protected Integer compute() {
        if (end - start <= THRESHOLD) {
            // Прямое выполнение для маленьких блоков
            int sum = 0;
            for (int i = start; i < end; i++) {
                sum += processTask(tasks[i]);
            }
            return sum;
        } else {
            // Разбиение на подзадачи
            int mid = (start + end) / 2;
            ParallelTaskProcessor left = new ParallelTaskProcessor(tasks, start, mid);
            ParallelTaskProcessor right = new ParallelTaskProcessor(tasks, mid, end);
            
            left.fork();
            int rightResult = right.compute();
            int leftResult = left.join();
            
            return leftResult + rightResult;
        }
    }
    
    private static int processTask(int task) {
        return task * 2; // Пример логики
    }
    
    public static void main(String[] args) {
        int[] tasks = new int[10000];
        for (int i = 0; i < tasks.length; i++) {
            tasks[i] = i;
        }
        
        ForkJoinPool pool = ForkJoinPool.commonPool();
        int result = pool.invoke(new ParallelTaskProcessor(tasks, 0, tasks.length));
        System.out.println("Result: " + result);
    }
}

4. Параллельные потоки (Stream API)

import java.util.stream.IntStream;

public class StreamParallel {
    public static void main(String[] args) {
        IntStream.range(0, 10000)
            .parallel()  // Включение параллелизма
            .forEach(i -> processTask(i));
    }
    
    private static void processTask(int taskId) {
        // Логика обработки
    }
}

Выбор подхода

МетодИспользованиеПреимущества
ExecutorServiceI/O операции, сетевые запросыПолный контроль, гибкость
CompletableFutureАсинхронные операции, цепочкиComposability, обработка результатов
ForkJoinPoolРекурсивные, CPU-интенсивные задачиWork-stealing, балансировка
parallel() StreamПростая параллелизация коллекцийЛаконичность, встроено в Java

Практические рекомендации

  1. Размер пула: 2-4 потока на ядро для I/O, 1 на ядро для CPU
  2. Обработка исключений: используй try-catch внутри задач
  3. Мониторинг: отслеживай использование памяти
  4. Graceful shutdown: всегда используй shutdown() и awaitTermination()

Лучший выбор для 10000 задач: ExecutorService с FixedThreadPool (8-16 потоков в зависимости от типа задач).

Как запустить потоки для решения 10000 задач | PrepBro