Читаем Многопоточное программирование в Java полностью

Как я уже говорил, классы ThreadPoolExecutor и ScheduledThreadPoolExecutor позволяют установить свои собственные настройки для объекта Executor и определить основной размер пула потоков, максимальный размер пула потоков, указать тип используемой очереди и другое.

Создание ExecutorService с помощью newFixedThreadPool эквивалентно использованию ThreadPoolExecutor с очередью LinkedBlockingQueue.



Эта очередь в данном случае неограниченна и упорядочивает элементы FIFO (первый пришел-первый ушел).

Новые элементы вставляются в хвост очереди, а элементы в начале очереди обрабатываются.

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

При этом если пул потоков не достиг еще своего основного размера, он создает новые потоки.

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

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

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

Здесь мы с помощью ThreadPoolExecutor создаем пул из двух потоков с очередью SynchronousQueue.



Эта очередь с нулевой емкостью.

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

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

Такой режим может быть полезен для незамедлительной обработки задач в фоне.

Фреймворк Fork-Join


Фреймворк Executor предоставляет несколько интерфейсов, таких как ExecutorService, для создания различных типов пулов потоков и выполнения ими задач.



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

В Java 7 добавлен класс ForkJoinPool, реализующий интерфейс ExecutorService и специально предназначенный для выполнения ForkJoinTask.

ForkJoinPool отличается от других видов ExecutorService главным образом благодаря реализации шаблона кража работы work-stealing.

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

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

ForkJoinPool имеет отдельные параллельные очереди, в отличие от Executor пула, который имеет только одну очередь.

Причем эти очереди являются очередями deque или двойными очередями (double ended queue), представляющими собой линейные коллекции, которые поддерживают вставку и удаление элементов на обоих концах.

Фреймворк Fork-Join разделяет задачу на большие подзадачи и обрабатывает каждую такую задачу в отдельном потоке.

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

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

Далее решения подзадач объединяются для получения окончательного результата.

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

Тогда он захватывает с конца другой очереди большую подзадачу и начинает с ней работать.

Это повышает эффективность выполнения по сравнению с Executor, где задача может болтаться в конце очереди очень долго.

Таким образом, резюмируя, фреймворк fork/join помогает ускорить параллельную обработку, пытаясь использовать все доступные ядра процессора с помощью подхода «разделяй и властвуй».

На практике это означает, что фреймворк сначала создает форки или «вилки», рекурсивно разбивая задачу на более мелкие независимые подзадачи, пока они не будут достаточно простыми, чтобы выполняться асинхронно.

После этого начинается этап «join», в котором результаты всех подзадач рекурсивно объединяются в один результат, или в случае задачи, которая ничего не возвращает, программа просто ждет, пока не будет выполнена каждая подзадача.

Чтобы обеспечить эффективное параллельное выполнение, фреймворк fork/join использует пул потоков, называемый ForkJoinPool, который управляет рабочими потоками, представленными классом ForkJoinWorkerThread, который расширяет класс Thread. Причем количество рабочих потоков в ForkJoinPool неограниченно, он может создавать дополнительные потоки по необходимости.

Класс ForkJoinPool является основой фреймворка и является реализацией интерфейса ExecutorService, управляя рабочими потоками и обеспечивая получение информации о состоянии пула потоков и производительности.

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

Вместо этого каждый поток в пуле имеет свою собственную двойную очередь (или deque), в которой хранятся задачи.

Эта архитектура обеспечивает балансировку рабочей нагрузки потока с помощью алгоритма воровства работы.

Перейти на страницу:

Похожие книги

«Ага!» и его секреты
«Ага!» и его секреты

Вы бы не хотели, скажем, изобрести что-то или открыть новый физический закон, а то и сочинить поэму или написать концерт для фортепьяно с оркестром?Не плохо бы, верно? Только как это сделать? Говорят, Шиллер уверял, будто сочинять стихи ему помогает запах гнилых яблок. И потому, принимаясь за работу, всегда клал их в ящик письменного стола. А физик Гельмгольц поступал иначе. Разложив все мысленно по полочкам, он дожидался вечера и медленно поднимался на гору лесной дорогой. Во время такой прогулки приходило нужное решение.Словом, сколько умов, столько способов заставить мозг работать творчески. А нет ли каких-то строго научных правил? Одинаковы ли они для математиков, биологов, инженеров, поэтов, художников? Да и существуют ли такие приемы, или каждый должен полагаться на свои природные способности и капризы вдохновения?Это тем более важно знать, что теперь появились «электронные ньютоны» — машины, специальность которых делать открытия. Но их еще нужно учить.Решающее слово здесь принадлежит биологам: именно они должны давать рецепты инженерам. А биологи и сами знают о том, как мы думаем, далеко не все. Им предстоит еще активнее исследовать лабораторию нашего мышления.О том, как ведутся эти исследования, как постепенно «умнеют» машины, как они учатся и как их учат, — словом, о новой науке эвристике рассказывает эта книга.

Елена Викторовна Сапарина

Зарубежная компьютерная, околокомпьютерная литература
Создание трилогии BioShock. От Восторга до Колумбии
Создание трилогии BioShock. От Восторга до Колумбии

Всего за три игры сага BioShock заняла особое место в сердцах игроков. Она может похвастаться проработанными и совершенно уникальными персонажами и мирами. Действие первых двух частей происходит в подводном городе Восторг, где игрок погружается в стиль ар-деко и атмосферу 1950-х годов. Третья часть, BioShock Infinite, переносит вас в 1912 год и приглашает исследовать небесный город Колумбия в сеттинге стимпанка.В книге вас ждут:[ul]рассуждение об источниках вдохновения создателя серии Кена Левина;исследование уникального геймплея и механик;подробности разработки игр франшизы от идеи до выпуска;глубокий анализ сюжета, тем и персонажей каждой части.[/ul]Авторы отдают дань уважения популярной серии игр, которая, несмотря на короткую историю, уже получила признание критиков.В формате PDF A4 сохранен издательский макет книги.

Мехди Эль Канафи , Николя Курсье , Рафаэль Люка

Зарубежная компьютерная, околокомпьютерная литература