Java Concurrency Guide: Анализ принципа работы пула потоков ThreadPoolTaskExecutor и избежание ошибок
Java Concurrency Guide: Анализ принципа работы пула потоков ThreadPoolTaskExecutor и избежание ошибок

Введение


Между потоками Java и потоками операционной системы существует взаимно однозначное соответствие.,Каждый раз, когда создается объект потока Java, операционная система будет отвечать за создание соответствующего системного потока.Потоки — это ценные ресурсы операционной системы. Создание и уничтожение очень дороги и неэффективны.。(в настоящий моментJDK19Уже появилсяВиртуальный поток-Виртуальный Threads предварительная версия )。

Чтобы улучшить производительность и облегчить управление потоками,В разработке,Мы обычноОговорено, что должен использоваться пул потоков, и вам не разрешено создавать потоки вручную.

В сценарии микросервиса используйте пул потоковчас,Чтобы избежать потери информации об отслеживании ссылок,долженИспользуйте пул потоков, инкапсулированный с информацией о ссылках, например TraceableExecutorService, в среде Spring Cloud.

[Следите за общедоступным аккаунтом: Техническая группа когнитивных технологий]

7 основных параметров и анализ пула потоков ThreadPoolTaskExecutor


Создайте конструктор, содержащий 7 основных параметров для пула потоков [необходимо использовать]

Язык кода:javascript
копировать
[Следите за общедоступным аккаунтом: Техническая группа когнитивных технологий]

public ThreadPoolExecutor(int corePoolSize,
                          int maximumPoolSize,
                          long keepAliveTime,
                          TimeUnit unit,
                          BlockingQueue<Runnable> workQueue,
                          ThreadFactory threadFactory,
                          RejectedExecutionHandler handler) {
        if (corePoolSize < 0 ||
            maximumPoolSize <= 0 ||
            maximumPoolSize < corePoolSize ||
            keepAliveTime < 0)
            throw new IllegalArgumentException();
        if (workQueue == null || threadFactory == null || handler == null)
            throw new NullPointerException();
        this.corePoolSize = corePoolSize;
        this.maximumPoolSize = maximumPoolSize;
        this.workQueue = workQueue;
        this.keepAliveTime = unit.toNanos(keepAliveTime);
        this.threadFactory = threadFactory;
        this.handler = handler;
    }
    

1. Количество основных потоков (corePoolSize) и максимальное количество потоков (maximumPoolSize).

Пул потоков автоматически поддерживает количество рабочих потоков в пуле потоков на основе значений corePoolSize и MaximumPoolSize. Общие правила следующие:

(1)кпул Когда поток отправляет задачу, если текущий пул потоковсередина Работа Количество потоковменьше, чем corePoolSize, для выполнения задачи будет создан новый поток, даже если другие рабочие потоки в пуле потоков простаивают.

Если основные потоки созданы заранее: prestartAllCoreThreads:

Язык кода:javascript
копировать
java.util.concurrent.ThreadPoolExecutor#prestartCoreThread
java.util.concurrent.ThreadPoolExecutor#prestartAllCoreThreads

Затем перейдите непосредственно к шагу (2).

(2)кпул Когда поток отправляет задачу, если текущий пул потоковсередина Работа Количество потоковЕсли значение больше, чем corePoolSize, но меньше, чем MaximumPoolSize, новый поток будет создан для выполнения задачи только тогда, когда рабочая очередь задач workQueue заполнена.

(3) Значения corePoolSize и MaximumPoolSize можно указывать не только в конструкторе.,иПоддержка динамической настройки среды выполнения пула потоков.

Язык кода:javascript
копировать
java.util.concurrent.ThreadPoolExecutor#setCorePoolSize
java.util.concurrent.ThreadPoolExecutor#setMaximumPoolSize

2. KeepAliveTime и единица измерения, время политики повторного использования простоя потока

По умолчанию,неосновные потокиОпределенно бесплатночас По истечении времени,Его необходимо выпустить и переработать,Это свободное времячас Пространство состоит изKeepAliveTime и единица измерения определяются совместно:

Язык кода:javascript
копировать
this.keepAliveTime = unit.toNanos(keepAliveTime);

Мы также можем динамически устанавливать значения в зависимости от условий задачи:

Язык кода:javascript
копировать
java.util.concurrent.ThreadPoolExecutor#setKeepAliveTime

Политика переработки простаивающих потоков по умолчанию предназначена только для неосновных потоков. Если вы хотите применить ее к основным потокам, мы должны отобразить настройки:

Язык кода:javascript
копировать
java.util.concurrent.ThreadPoolExecutor#allowsCoreThreadTimeOut

Когда рабочие потоки в пуле потоков запускаются,

Язык кода:javascript
копировать
java.util.concurrent.ThreadPoolExecutor.Worker#run

Этот рабочий поток работает до тех пор, пока первая задача или задача может быть получена из очереди задач. KeepAliveTime в основном используется для получения головной задачи из тайм-аута блокировки очереди задач.

Если этот рабочий поток простаивает в течение KeepAliveTime, то есть очередь задач блокирует тайм-аут KeepAliveTime для получения задачи руководителя группы. Когда задача не может быть получена, устанавливается флаг тайм-аута. В следующий раз цикл for оценивается в соответствии с. в соответствии с политикой тайм-аута, следует ли войти в цикл for, чтобы снова получить задачу из очереди задач, или NULL возвращается после тайм-аута, что приводит к завершению рабочего потока и его повторному использованию.

3. workQueue, очередь задач

Основная функция очереди задач workQueue — кэширование отправленных задач. Когда количество потоков пула потоков превышает количество неосновных потоков и не превышает максимальное количество потоков, отправленные задачи кэшируются в этой очереди задач. Потоки в пуле потоков всегда будут использовать задачи из этой очереди задач.

Избегайте ловушек: рекомендуется использовать очередь задач с ограниченной емкостью, чтобы накопление задач не приводило к возникновению OOM.

4. Фабрика потоков threadFactory

Главное задать имя треда при создании треда.、атрибут демона、Приоритет и другие атрибуты。Хорошие имена потоков можно использовать для анализа и решения проблем с помощью команды jstack.

Реализация по умолчанию java.util.concurrent.Executors.DefaultThreadFactory:

Рекомендуется использовать org.apache.commons.lang3.concurrent.BasicThreadFactory.Builder:

Язык кода:javascript
копировать


BasicThreadFactory factory = new BasicThreadFactory.Builder()
                .namingPattern("поток когнитивных технологий-%d")
                .daemon(true)
                .priority(Thread.MAX_PRIORITY)
                .build();

5. Стратегия отклонения задач пула потоков-обработчиков

При отправке задачи в пул потоков текущее количество потоков превышает максимальное количество потоков MaximumPoolSize. В это время основные потоки заняты, очередь задач заполнена, и отправленная задача будет отклонена. Конечно, если пул потоков отключается, отправка также будет отклонена.

JUC предоставляет несколько реализаций по умолчанию:

(1)ThreadPoolExecutor.AbortPolicy

Если пул потоков не устанавливает политику отклонения задач, политикой по умолчанию является AbortPolicy, выдавая исключение:

RejectedExecutionException отклоняет отправку задачи.

(2)ThreadPoolExecutor.CallerRunsPolicy

Если поток, отправивший задачу, выполняет задачу, то есть поток, который в данный момент отправляет задачу, непосредственно выполняет задачу, вызывая Runnable.run(), который заблокирует текущий поток.

Как правило, при использовании этой стратегии журналы следует распечатывать и сообщать о них.

Язык кода:javascript
копировать
new ThreadPoolExecutor.CallerRunsPolicy() {
                    @Override
                    public void rejectedExecution(Runnable r, ThreadPoolExecutor e) {
                        log.info("rejectedExecution ");
                        super.rejectedExecution(r, e);
                    }
                }

Общий сценарий использования: замена последовательных вызовов на параллельные вызовы, чтобы настройки пула потоков не были недостаточными и не переросли в последовательные вызовы. Когда задача отклоняется, размер пула потоков динамически корректируется для поиска подходящих параметров.

(3)ThreadPoolExecutor.DiscardPolicy

Отклоненные задачи молча отбрасываются, ничего не делается и даже лог не печатается.

Эта политика запрещена во время разработки.

Если вы вернете Future после отправки задачи в пул потоков и используете метод get без таймаута для получения результата, вас могут заблокировать навсегда.

Избегайте ловушек Цуй Жижи,Официальный аккаунт:Техническая команда когнитивных технологийПараллелизм Java: как FutureTask выполняет многопоточное одновременное выполнение и асинхронное получение результатов задач? И как избежать подводных камней

(4)ThreadPoolExecutor.DiscardOldestPolicy

Очередь потерянных задач отбрасывает головную задачу и пытается снова отправить задачу в пул потоков.

Эта стратегия не рекомендуется.

Чтобы реализовать политику отклонения задач вышеуказанного пула потоков, нам обычно необходимо наследовать ее и добавить операцию печати журнала.

Отправьте задачу в процесс пула потоков ThreadPoolTaskExecutor.


Как показано ниже:

(1) При отправке задачи в пул потоков, если количество рабочих потоков в текущем пуле потоков меньше, чем corePoolSize, будет создан новый поток для выполнения задачи, даже если другие рабочие потоки в пуле потоков простаивают. .

(2) Если при отправке задачи в пул потоков количество рабочих потоков в текущем пуле потоков превышает corePoolSize, текущая задача сохраняется в рабочей очереди задач workQueue.

(3) При отправке задачи в пул потоков, если количество рабочих потоков в текущем пуле потоков больше, чем corePoolSize, но меньше, чем MaximumPoolSize, а рабочая очередь задачи workQueue заполнена, создается новый поток для выполнения задачи. .

(4) При отправке задачи в пул потоков, если количество рабочих потоков в текущем пуле потоков превышает corePoolSize, а рабочая очередь задачи workQueue заполнена, а количество рабочих потоков в текущем пуле потоков больше чем MaximumPoolSize, будет выполнена политика отклонения задачи, чтобы отклонить отправку задачи.

пул потоковThreadPoolTaskExecutorИзбегайте ловушек


boy illustration
Учебное пособие по Jetpack Compose для начинающих, базовые элементы управления и макет
boy illustration
Код js веб-страницы, фон частицы, код спецэффектов
boy illustration
【новый! Суперподробное】Полное руководство по свойствам компонентов Figma.
boy illustration
🎉Обязательно к прочтению новичкам: полное руководство по написанию мини-программ WeChat с использованием программного обеспечения Cursor.
boy illustration
[Забавный проект Docker] VoceChat — еще одно приложение для мгновенного чата (IM)! Может быть встроен в любую веб-страницу!
boy illustration
Как реализовать переход по странице в HTML (html переходит на указанную страницу)
boy illustration
Как решить проблему зависания и низкой скорости при установке зависимостей с помощью npm. Существуют ли доступные источники npm, которые могут решить эту проблему?
boy illustration
Серия From Zero to Fun: Uni-App WeChat Payment Practice WeChat авторизует вход в систему и украшает страницу заказа, создает интерфейс заказа и инициирует запрос заказа
boy illustration
Серия uni-app: uni.navigateЧтобы передать скачок значения
boy illustration
Апплет WeChat настраивает верхнюю панель навигации и адаптируется к различным моделям.
boy illustration
JS-время конвертации
boy illustration
Обеспечьте бесперебойную работу ChromeDriver 125: советы по решению проблемы chromedriver.exe не найдены
boy illustration
Поле комментария, щелчок мышью, специальные эффекты, js-код
boy illustration
Объект массива перемещения объекта JS
boy illustration
Как открыть разрешение на позиционирование апплета WeChat_Как использовать WeChat для определения местонахождения друзей
boy illustration
Я даю вам два набора из 18 простых в использовании фонов холста Power BI, так что вам больше не придется возиться с цветами!
boy illustration
Получить текущее время в js_Как динамически отображать дату и время в js
boy illustration
Вам необходимо изучить сочетания клавиш vsCode для форматирования и организации кода, чтобы вам больше не приходилось настраивать формат вручную.
boy illustration
У ChatGPT большое обновление. Всего за 45 минут пресс-конференция показывает, что OpenAI сделал еще один шаг вперед.
boy illustration
Copilot облачной разработки — упрощение разработки
boy illustration
Микросборка xChatGPT с низким кодом, создание апплета чат-бота с искусственным интеллектом за пять шагов
boy illustration
CUDA Out of Memory: идеальное решение проблемы нехватки памяти CUDA
boy illustration
Анализ кластеризации отдельных ячеек, который должен освоить каждый&MarkerгенетическийВизуализация
boy illustration
vLLM: мощный инструмент для ускорения вывода ИИ
boy illustration
CodeGeeX: мощный инструмент генерации кода искусственного интеллекта, который можно использовать бесплатно в дополнение к второму пилоту.
boy illustration
Машинное обучение Реальный бой LightGBM + настройка параметров случайного поиска: точность 96,67%
boy illustration
Бесшовная интеграция, мгновенный интеллект [1]: платформа больших моделей Dify-LLM, интеграция без кодирования и встраивание в сторонние системы, более 42 тысяч звезд, чтобы стать свидетелями эксклюзивных интеллектуальных решений.
boy illustration
LM Studio для создания локальных больших моделей
boy illustration
Как определить количество слоев и нейронов скрытых слоев нейронной сети?
boy illustration
[Отслеживание целей] Подробное объяснение ByteTrack и детали кода