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
Неразрушающее увеличение изображений одним щелчком мыши, чтобы сделать их более четкими артефактами искусственного интеллекта, включая руководства по установке и использованию.
boy illustration
Копикодер: этот инструмент отлично работает с Cursor, Bolt и V0! Предоставьте более качественные подсказки для разработки интерфейса (создание навигационного веб-сайта с использованием искусственного интеллекта).
boy illustration
Новый бесплатный RooCline превосходит Cline v3.1? ! Быстрее, умнее и лучше вилка Cline! (Независимое программирование AI, порог 0)
boy illustration
Разработав более 10 проектов с помощью Cursor, я собрал 10 примеров и 60 подсказок.
boy illustration
Я потратил 72 часа на изучение курсорных агентов, и вот неоспоримые факты, которыми я должен поделиться!
boy illustration
Идеальная интеграция Cursor и DeepSeek API
boy illustration
DeepSeek V3 снижает затраты на обучение больших моделей
boy illustration
Артефакт, увеличивающий количество очков: на основе улучшения характеристик препятствия малым целям Yolov8 (SEAM, MultiSEAM).
boy illustration
DeepSeek V3 раскручивался уже три дня. Сегодня я попробовал самопровозглашенную модель «ChatGPT».
boy illustration
Open Devin — инженер-программист искусственного интеллекта с открытым исходным кодом, который меньше программирует и больше создает.
boy illustration
Эксклюзивное оригинальное улучшение YOLOv8: собственная разработка SPPF | SPPF сочетается с воспринимаемой большой сверткой ядра UniRepLK, а свертка с большим ядром + без расширения улучшает восприимчивое поле
boy illustration
Популярное и подробное объяснение DeepSeek-V3: от его появления до преимуществ и сравнения с GPT-4o.
boy illustration
9 основных словесных инструкций по доработке академических работ с помощью ChatGPT, эффективных и практичных, которые стоит собрать
boy illustration
Вызовите deepseek в vscode для реализации программирования с помощью искусственного интеллекта.
boy illustration
Познакомьтесь с принципами сверточных нейронных сетей (CNN) в одной статье (суперподробно)
boy illustration
50,3 тыс. звезд! Immich: автономное решение для резервного копирования фотографий и видео, которое экономит деньги и избавляет от беспокойства.
boy illustration
Cloud Native|Практика: установка Dashbaord для K8s, графика неплохая
boy illustration
Краткий обзор статьи — использование синтетических данных при обучении больших моделей и оптимизации производительности
boy illustration
MiniPerplx: новая поисковая система искусственного интеллекта с открытым исходным кодом, спонсируемая xAI и Vercel.
boy illustration
Конструкция сервиса Synology Drive сочетает проникновение в интрасеть и синхронизацию папок заметок Obsidian в облаке.
boy illustration
Центр конфигурации————Накос
boy illustration
Начинаем с нуля при разработке в облаке Copilot: начать разработку с минимальным использованием кода стало проще
boy illustration
[Серия Docker] Docker создает мультиплатформенные образы: практика архитектуры Arm64
boy illustration
Обновление новых возможностей coze | Я использовал coze для создания апплета помощника по исправлению домашних заданий по математике
boy illustration
Советы по развертыванию Nginx: практическое создание статических веб-сайтов на облачных серверах
boy illustration
Feiniu fnos использует Docker для развертывания личного блокнота Notepad
boy illustration
Сверточная нейронная сеть VGG реализует классификацию изображений Cifar10 — практический опыт Pytorch
boy illustration
Начало работы с EdgeonePages — новым недорогим решением для хостинга веб-сайтов
boy illustration
[Зона легкого облачного игрового сервера] Управление игровыми архивами
boy illustration
Развертывание SpringCloud-проекта на базе Docker и Docker-Compose