Один трюк, который вы могли бы сделать, - это иметь очередь из очередей. Поэтому вы должны иметь одну очередь блокировки, на которую подписываются все потоки. Затем, когда вы помещаете что-то в одну из ваших блокирующих очередей, вы также ставите свою очередь на блокировку в этой единственной очереди. Так что у вас будет что-то вроде:
BlockingQueue<WorkItem> producers[] = new BlockingQueue<WorkItem>[NUM_PRODUCERS];
BlockingQueue<BlockingQueue<WorkItem>> producerProducer = new BlockingQueue<BlockingQueue<WorkItem>>();
Тогда, когда вы получите новый рабочий элемент:
void addWorkItem(int queueIndex, WorkItem workItem) {
assert queueIndex >= 0 && queueIndex < NUM_PRODUCERS : "Pick a valid number";
//Note: You may want to make the two operations a single atomic operation
producers[queueIndex].add(workItem);
producerProducer.add(producers[queueIndex]);
}
Теперь ваши потребители могут все блокировать от производителяПроизводитель. Я не уверен, насколько ценна эта стратегия, но она выполняет то, что вы хотите.