I have a java app using Spring framework. My application consists on multiple producers and once consumer.
I declare a shared queue between producers and consumers like this:
<bean id="theQueue" class="java.util.concurrent.LinkedBlockingQueue"/>
this queue is passed to the producers constructor and to the consumer construtor as below.
<bean id="Consumer" class="com.app.Consumer">
<constructor-arg ref="theQueue"/>
</bean>
<bean id="Producer1" class="com.app.Producer">
<constructor-arg ref="theQueue"/>
</bean>
<bean id="Producer2" class="com.app.producer">
<constructor-arg ref="theQueue"/>
</bean>
<bean id="Producer3" class="com.app.producer">
<constructor-arg ref="theQueue"/>
</bean>
Constructors are like below:
package com.app.producer;
public class Producer implements Runnable {
private final Queue<Message> queue;
public Producer (Queue<Message> queue) {
this.queue = queue;
}
...
public void run() {
while (someCondition) {
...
this.queue.add(Message);
...
}
}
}
package com.app.Consumer;
public class Consumer implements Runnable {
private final BlockingQueue<Message> queue;
public Consumer(BlockingQueue<Message> queue) {
this.queue = queue;
}
...
public void run() {
while (true) {
...
Message message = this.queue.take();
...
}
}
}
Application starts correctly but after some time, producer adds elements to queue but consumer remains waiting in the queue. Seems like consumer is not awaken by producer when it inserts elements into the queue. However if I change the queue type from PriorityBlockingQueue to BlockingQueue it works, that is, replacing:
private final PriorityBlockingQueue<Message> queue;
by
private final BlockingQueue<Message> queue;
Message implements Comparable like below:
public class Message implements Comparable<Message> {
public enum Priority{
NORMAL,
HIGH,
URGENT
}
private final String msg;
private final Priority priority;
public Message(String msg, Priority priority) {
this.msg = msg;
this.priority = priority;
}
...
public int compareTo(Message compareMessage) {
int retVal = (int) (compareMessage.priority.ordinal() - this.priority.ordinal());
return retVal;
}
}
Why PriorityBlockingQueue does not behave as expected? I don't understand why consumer remains waiting for elements in the queue to be ready if producers have just added them to the queue.