Реализация этой функциональности непроста, поскольку вам нужно либо иметь отдельные очереди для каждой цели (так что код ожидания становится намного более сложным), либо одну очередь, из которой вы затем пропускаете целевые объекты, которые загружены (что приводит к снижению производительности)).Вы можете попытаться расширить ExecutorService для достижения этой цели, но расширение кажется нетривиальным.
Обновленный ответ / решение:
Подумав немного об этом, самое простое решениепроблема блокировки состоит в том, чтобы иметь как очередь блокировки (как обычно), так и карту очередей (одна очередь на цель, а также количество доступных потоков на цель).Карта очередей используется только для задач, которые были переданы для выполнения (из-за слишком большого количества потоков, уже запущенных для этой цели) после того, как задача извлечена из обычной очереди блокировки.
Таким образом, поток выполнения будетвыглядит следующим образом:
- задание отправляется (с определенной целью) с помощью вызывающего кода.
- Задача помещается в очередь блокировки (вероятно, заключенная в нее вашим собственным классом задачи, который включает в себя цельинформация).
- поток (из пула потоков) ожидает в очереди блокировки (с помощью take ()).
- поток принимает отправленную задачу.
- поток синхронизируется поблокировка.
- поток проверяет доступное количество для этой цели.
, если доступное количество> 0
- , то поток уменьшает количество на 1, освобождаетблокировка, запускает задачу.
- иначе поток помещает задачу в карту цели в очередь задач (эта карта представляет собой , переданную по карте задач ), снимает блокировку и возвращается к ожиданиюна тблокирующая очередь.
когда поток завершает выполнение задачи, он:
- синхронизируется при блокировке.
- проверяетсчитать для цели, которую она только что выполнила.
- если счет == 0
- , то проверьте переданную карту задач для любых задач для этой цели, если она существует, затем снимите блокировку и запустите ее.
- , если для счетчика не было 0 или для той же цели не было заданий в переданной карте / очереди, затем увеличьте доступное количество (для этой цели), снимите блокировку ивернитесь к ожиданию в очереди блокировки.
Это решение позволяет избежать значительного снижения производительности или использования отдельного потока только для управления очередью.