JavaRush/Курсы/Java Multithreading/ThreadPoolExecutor пул нитей

ThreadPoolExecutor пул нитей

Открыта
ThreadPoolExecutor пул нитей - 1

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

Если ты пишешь игру, то это действия, которые выполняют отдельные персонажи.

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

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

Вот так на этом фоне незаметно и возникает вопрос – а как ими всеми управлять? Если в минуту нужно выполнить несколько сотен задач? Создавать для каждой задачи свою нить бывает не очень рационально. Для каждой нити Java-машина выделяет довольно много ресурсов.

Другими словами – создание и уничтожение отработавшей нити может тратить больше ресурсов и времени, чем само выполняемое задание.

Java-разработчики придумали элегантное решение этой проблемы — ThreadPoolExecutor.

ThreadPoolExecutor – это класс, который имеет внутри две вещи:

А) Очередь задач, в которую можно добавлять задачи, по мере их появления в программе.

Б) Пул-нитей (группа нитей) – которые эти задачи исполняют.

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

При создании ThreadPoolExecutor, можно задать максимальное количество нитей, которые будут созданы и максимальное количество заданий, которые можно поместить в очередь. Т.е. можно ограничить количество нитей числом 10, например, а количество задач в очереди – 100.

Как работает ThreadPoolExecutor:

1) При добавлении нового задания, оно помещается в конец очереди.

2) Если очередь заполнена будет выкинуто исключение.

3) Каждая нить после выполнения задания берет очередное задание из очереди и начинает выполнять его.

4) Если задач в очереди нет, нить засыпает до их добавления.

Подход с ограничением количества работающих нитей выгоден тем, что чем больше нитей, тем сильнее они друг другу мешают. Гораздо эффективнее иметь 5-10 нитей-исполнителей и длинную очередь задач, чем создать 100 нитей для внезапно появившейся группы задач, которые будет конкурировать друг с другом за ресурсы: память, время процессора, доступ к базе и т.п.

Пример работы такого ThreadPoolExecutor:
<

Пример
ExecutorService service = Executors.newFixedThreadPool(2);

for(int i = 0; i < 10; i++) {
 service.submit(new Runnable() { public void run()
    {
     // тут мы загружаем что-то тяжелое из интернета.
    }
 });
}

— Я что-то не вижу его…

— Объект ThreadPoolExecutor создается при вызове метода newFixedThreadPool.

Так вот, работает он очень просто. Как только ты добавляешь ему задачу с помощью метода submit, он:

А) Будит спящую нить для ее выполнения, если такая есть.

Б) Создает новую нить для выполнения задания, если ее нет.

В) Если достигнут максимум нитей, то просто кладет задачу в конец очереди.

Я специально написала в примере – тут мы загружаем что-то тяжелое из интернета. Если у нас есть 100 задач «скачать что-то большое из интернета», то нет смысла запускать много таких задач одновременно – мы упремся в ограничение ширины интернет-канала. В таком случает пары нитей должно быть достаточно. Именно это ты и видишь в примере выше:

ExecutorService service = Executors.newFixedThreadPool(2);

— Оказывается, работать с кучей задач не так уж и сложно.

— Да. Даже легче, чем ты можешь себе представить. Но об этом тебе расскажет Ким.

Комментарии (47)
  • популярные
  • новые
  • старые
Для того, чтобы оставить комментарий Вы должны авторизоваться
Алексей
Уровень 1
1 мая 2025, 13:01
С детства обожаю эти карикатуры. Со мной все нормально?
SE GA
Уровень 41
26 апреля 2024, 16:11
КамушекJava Developer в Иннотех
23 декабря 2023, 17:29
Thread'ом Java не испортишь: Часть V — Executor, ThreadPool, Fork Join ExecutorService Java ThreadPoolExecutor prestartAllCoreThreads() shutdown() - ждет завершения запущенных задач, ничего не возвращает. shutdownNow( )- останавливает исполнитель немедленно и возвращает список незавершенных задач.
alexyng7
Уровень 32
14 ноября 2023, 09:52
Rolik
Уровень 41
26 апреля 2023, 11:57
Честно ? Ору... Просто представил поплавленный мозг человека, на которого так сходу вывалили 2 интерфейса и 3 класса создания и управления пулом потоков и чтоб наверняка, добили лопатой лямбдой. И все это в одной коротенькой лекции. :)
TaurnilTechnical Lead в ООО "Теком"
3 июня 2023, 17:27
Это не лямбда, это анонимный класс. Эта штука уже давно должна была в голове осесть и восприниматься как должное, столько уже задач было, где анонимные классы явно или неявно приходилось использовать. Лямбда выглядела бы вот так:
service.submit(() -> doExpensiveOperation(i));
А по теме очередей потоков рекомендую посмотреть Алишева. У него несколько роликов есть про многопоточность, где подробно разбирается эта(ThreadPoolExecutor, Executors, ExecutorService) тема.
Rolik
Уровень 41
4 июня 2023, 05:55
Какой раздел и номер уровня ? Хочу посмотреть где ошибся.
TaurnilTechnical Lead в ООО "Теком"
4 июня 2023, 08:19
Анонимные класы явно разбираются в этом разделе: https://javarush.com/quests/lectures/questmultithreading.level03.lecture07 Но первое упоминание было в конце Syntax, в разделе с лямбдами или около того. https://javarush.com/quests/lectures?quest=QUEST_JAVA_SYNTAX&level=19 Лямбда, по отношению к переопределению метода функционального интерфейса, это, по сути, упрощенно-обобщенная запись объявления анонимного класса. Через такую парадигму гораздо проще это понять. Если ты не разбираешься в задачах или копируешь готовое решение, не вникая в тему (потому что эта тема еще явно не разжевывалась), то хотя бы не решай их, а возвращайся к ним позднее, когда понимание придет.
Rolik
Уровень 41
4 июня 2023, 12:50
Я просил ссылку на тему где я оставил комментарий. Я хочу проверить - действительно ли я ошибся, и анонимный класс в примере/задаче был объявлен без использования лямбда выражения. По сути, лямбда выражение и есть сокращенная запись анонимного внутреннего класса.
TaurnilTechnical Lead в ООО "Теком"
4 июня 2023, 16:54
Что ты имеешь ввиду? Тебе нужна ссылка на текущую ветку штолле? XD https://javarush.com/quests/lectures/questmultithreading.level08.lecture07
Rolik
Уровень 41
4 июня 2023, 18:12
Именно. Я из аппы не могу выйти обратно в тему. Да, лямбды в теме нет. Очевидно перелистывая конспект, спутал примеры в JR и конспекте. Приношу извинения.
Kirill
Уровень 46
3 декабря 2024, 20:11
Между лямбдами и анонимными классами есть существенная разница: лямбды, в отличие от анонимных классов, не имеют собственного this (их контекст исполнения - окружающий их объект/класс). Соответственно после компиляции для лямбда выражений не создаётся отдельный class-файл.
BALENCIAGA DEV
Уровень 51
11 апреля 2025, 19:29
Я надеюсь у вас все хорошо и вы во всем разобрались, извините но я просто в ахуе с того какие softskills проявляет человек у которого прописано Technical Lead в ООО "Теком". Я теперь начинаю понимать откуда возник такой вой вокруг данной темы.
Griboed
Уровень 30
5 апреля 2023, 07:48
чувствую я, тема маст хэв. =)
22 ноября 2022, 13:14
Ничего не сказано про shutdown. Возможно это лишняя, мусорная информация. Но это не точно.
Zhenya Workout
Уровень 43
20 марта 2023, 17:54
Да, остановить сервис это мусорная задача)
Gans Electro
Уровень 4
23 июня 2023, 12:39
Дальше есть парни
Bakyt Sarmanov
Уровень 50
1 июня 2022, 09:39
Пример работы такого ThreadPoolExecutor: < как же хочется убрать это😀
11 апреля 2021, 05:43
newFixedThreadPool(2)
2 - обозначает, что создается пул с двумя потоками.
Роман Юрьевич
Уровень 38
14 августа 2021, 14:40
Информация для тех, кто дошел до данного уровня просто копируя решения задач из комментариев😄
Уровень 51
25 декабря 2022, 15:40
М?А у меня есть волшебная кнопка "Показать решение"...
5 декабря 2020, 09:53
Зачем ограничивать очередь задач? На что это влияет?
Flexo Bending Unit #3370318
12 июля 2021, 16:21
по умолчанию ограничение очереди в Integer.MAX_VALUE, это с лихвой хватает для всего но можно и ограничить, что, видимо, позволит управлять ресурсами занимаемой памяти
CyberBoar
Уровень 1
3 августа 2022, 15:31
Видимо для того, чтобы не создавать ситуаций, когда очередь заполнена невыполнимым количеством задач.
Виктор
Уровень 1
2 октября 2022, 15:11
ограничивается не очередь,а количество одновременно работающих нитей.