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

Что такое FixedThreadPool?

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

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

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

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

FixedThreadPool: пул потоков с фиксированным размером

FixedThreadPool — это реализация ExecutorService из пакета java.util.concurrent, которая создаёт пул с фиксированным числом рабочих потоков. Это один из самых популярных и простых способов управления многопоточностью в Java.

Основная концепция

FixedThreadPool содержит определённое количество потоков, которые переиспользуются для выполнения задач:

// Создание FixedThreadPool на 5 потоков
ExecutorService executor = Executors.newFixedThreadPool(5);

// Теперь этот пул будет содержать ровно 5 потоков
// Все задачи выполняются этими 5 потоками

Как это работает

public class FixedThreadPoolExample {
    public static void main(String[] args) {
        // Создаём пул из 3 потоков
        ExecutorService executor = Executors.newFixedThreadPool(3);
        
        // Отправляем 10 задач
        for (int i = 1; i <= 10; i++) {
            final int taskNumber = i;
            executor.submit(() -> {
                System.out.println("Task " + taskNumber + " started by " + 
                    Thread.currentThread().getName());
                try {
                    Thread.sleep(1000);  // Имитируем работу
                } catch (InterruptedException e) {
                    Thread.currentThread().interrupt();
                }
                System.out.println("Task " + taskNumber + " finished");
            });
        }
        
        // Вывод будет примерно:
        // Task 1 started by pool-1-thread-1
        // Task 2 started by pool-1-thread-2
        // Task 3 started by pool-1-thread-3
        // (остальные 7 задач ждут в очереди)
        // Task 4 started by pool-1-thread-1  (когда thread-1 закончила)
        
        executor.shutdown();  // Корректно завершаем пул
    }
}

Внутренняя структура

// Упрощённая реализация FixedThreadPool
public class SimplifiedFixedThreadPool {
    private final ExecutorService executor = Executors.newFixedThreadPool(3);
    
    // Внутри:
    // - ThreadPoolExecutor с: corePoolSize = 3, maxPoolSize = 3
    // - LinkedBlockingQueue для хранения задач
    // - 3 рабочих потока, которые берут задачи из очереди
}

Основные параметры:

  • corePoolSize = количество потоков (например, 5)
  • maxPoolSize = максимум потоков (также 5 для FixedThreadPool)
  • queue = LinkedBlockingQueue (неограниченная очередь)

Практический пример: обработка запросов

public class RequestProcessor {
    private final ExecutorService executor = Executors.newFixedThreadPool(10);
    private final List<String> results = Collections.synchronizedList(new ArrayList<>());
    
    public void processRequests(List<String> requests) {
        for (String request : requests) {
            executor.submit(() -> {
                String result = handleRequest(request);
                results.add(result);
            });
        }
    }
    
    private String handleRequest(String request) {
        // Обработка запроса (может быть медленной)
        try {
            Thread.sleep(100);
        } catch (InterruptedException e) {
            Thread.currentThread().interrupt();
        }
        return "Processed: " + request;
    }
    
    public void waitForCompletion() throws InterruptedException {
        executor.shutdown();
        if (!executor.awaitTermination(5, TimeUnit.MINUTES)) {
            executor.shutdownNow();
        }
    }
}

Разница между execute и submit

public class ExecuteVsSubmit {
    public static void main(String[] args) throws ExecutionException, InterruptedException {
        ExecutorService executor = Executors.newFixedThreadPool(2);
        
        // execute(Runnable) - не возвращает результат
        executor.execute(() -> System.out.println("Runnable task"));
        
        // submit(Runnable) - возвращает Future<Void>
        Future<Void> future1 = executor.submit(() -> System.out.println("Submit runnable"));
        future1.get();  // Ждём завершения
        
        // submit(Callable<T>) - возвращает Future<T>
        Future<String> future2 = executor.submit(() -> "Result");
        String result = future2.get();  // Получаем результат
        System.out.println(result);
        
        executor.shutdown();
    }
}

Корректное завершение пула

public class ProperShutdown {
    public static void main(String[] args) throws InterruptedException {
        ExecutorService executor = Executors.newFixedThreadPool(3);
        
        // Отправляем задачи
        for (int i = 0; i < 10; i++) {
            executor.submit(() -> {
                System.out.println(Thread.currentThread().getName());
            });
        }
        
        // Способ 1: Graceful shutdown
        executor.shutdown();  // Не принимает новые задачи, ждёт окончания
        
        // Ждём максимум 10 секунд
        if (!executor.awaitTermination(10, TimeUnit.SECONDS)) {
            // Если не закончилось за 10 сек
            List<Runnable> pendingTasks = executor.shutdownNow();  // Прерываем
            System.out.println("Pending tasks: " + pendingTasks.size());
        }
        
        System.out.println("Executor terminated");
    }
}

Сравнение типов пулов

public class ThreadPoolComparison {
    public static void main(String[] args) {
        // 1. FixedThreadPool - фиксированное количество потоков
        ExecutorService fixed = Executors.newFixedThreadPool(5);
        // Хорошо для: predictable workload, ограниченные ресурсы
        
        // 2. CachedThreadPool - динамичное количество
        ExecutorService cached = Executors.newCachedThreadPool();
        // Хорошо для: много коротких задач, переменная нагрузка
        
        // 3. SingleThreadExecutor - один поток
        ExecutorService single = Executors.newSingleThreadExecutor();
        // Хорошо для: последовательные задачи, гарантия порядка
        
        // 4. ScheduledThreadPool - для периодических задач
        ScheduledExecutorService scheduled = Executors.newScheduledThreadPool(5);
        // Хорошо для: задачи по расписанию
    }
}

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

// ✓ ХОРОШО: обработка HTTP запросов на веб-сервере
public class WebServer {
    private final ExecutorService executor = Executors.newFixedThreadPool(100);
    
    public void handleRequest(HttpRequest request) {
        executor.submit(() -> {
            // Обработка запроса в отдельном потоке
            processRequest(request);
        });
    }
}

// ✓ ХОРОШО: обработка задач из очереди
public class TaskProcessor {
    private final ExecutorService executor = Executors.newFixedThreadPool(5);
    
    public void processTasksFromQueue(Queue<Task> taskQueue) {
        while (!taskQueue.isEmpty()) {
            Task task = taskQueue.poll();
            executor.submit(() -> task.execute());
        }
    }
}

// ❌ ПЛОХО: очень много задач одновременно
ExecutorService executor = Executors.newFixedThreadPool(1000000);  // Память!

// ❌ ПЛОХО: если нужна гибкость размера
// Используй ScheduledThreadPool или CachedThreadPool

Memory Usage

public class MemoryExample {
    public static void main(String[] args) throws InterruptedException {
        // FixedThreadPool с 1000 потоков
        ExecutorService executor = Executors.newFixedThreadPool(1000);
        // Каждый поток занимает ~1MB памяти (stack)
        // Итого: ~1GB памяти только на потоки!
        
        // Поэтому:
        // - Маленькие пулы (10-20) для обработки запросов
        // - Большие пулы (100+) только для специфических случаев
        
        executor.shutdown();
    }
}

Best Practices

public class BestPractices {
    // 1. Размер пула зависит от нагрузки
    // Для I/O-bound: pool_size = 2 * number_of_cpus
    // Для CPU-bound: pool_size = number_of_cpus
    
    private static final int OPTIMAL_POOL_SIZE = 
        Runtime.getRuntime().availableProcessors() * 2;
    
    private final ExecutorService executor = 
        Executors.newFixedThreadPool(OPTIMAL_POOL_SIZE);
    
    // 2. Обрабатывай исключения
    public void submitTask() {
        executor.submit(() -> {
            try {
                doWork();
            } catch (Exception e) {
                logger.error("Task failed", e);
            }
        });
    }
    
    // 3. Корректно завершай
    public void shutdown() throws InterruptedException {
        executor.shutdown();
        executor.awaitTermination(1, TimeUnit.MINUTES);
    }
}

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