0

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.

Willy
  • 9,848
  • 22
  • 141
  • 284
  • do your Message instances implement a stable sort? – jtahlborn Feb 12 '16 at 19:04
  • @jtahlborn My Message class implements Comparable object and then I override compareTo method as I indicate in the post. See my post edited, I have put my Message class. Message class has an enum in which compareTo method is based in order to sort the messages. – Willy Feb 12 '16 at 22:46
  • Why are you a casting an int to an int? – user207421 Feb 13 '16 at 00:33
  • @EJP Ooopsss sorry you are right, it is not necessary ;) but I don't think it can be the cause of my problem. – Willy Feb 13 '16 at 04:04

0 Answers0