Ted Gress
Ted Gress

Reputation: 21

ClassCastException when using PriorityBlockingQueue

I'm trying to make a simple message manager for my game. However, I'm getting the following exception:

Exception in thread "main" Exception in thread "Thread-4" java.lang.ClassCastException: MessageManagement.Message cannot be cast to java.lang.Comparable
at java.util.concurrent.PriorityBlockingQueue.siftUpComparable(Unknown Source)
at java.util.concurrent.PriorityBlockingQueue.offer(Unknown Source)
at java.util.concurrent.PriorityBlockingQueue.add(Unknown Source)
at MessageManagement.MessageManager.EnqueueMessage(MessageManager.java:69)

The initialization code is:

MessageManager messageManager = new MessageManager();
messageManager.start();

//send bootstrap message
CJournal.Journal(Main.class, "Testing messanger: ending bootstrapping message to messagemanager");
Message boot_strap_message = new Message();
boot_strap_message.mflag = EEventMachine.EM_BOOTSTRAP;
messageManager.EnqueueMessage(boot_strap_message);

And the actual message manager is:

public  class MessageManager extends Thread {

    @Override
    public  void run() {
        // TODO Auto-generated method stub
        while (true)
        {

            if (!messagesQueue.isEmpty())
            {
                //pull message from queue
                Message message = messagesQueue.remove();

                //dispatch messages according to their type
                switch(message.mflag)
                {
                case EM_BOOTSTRAP:
                    CJournal.Journal(MessageManager.class, "Messaging system working properly.");
                default:
                    CJournal.Journal(MessageManager.class, "Dispatch Message Trashed");
                }
            }
        }
    }

    public static PriorityBlockingQueue<Message> messagesQueue = new PriorityBlockingQueue<Message>();

    public static void EnqueueMessage(Message message)
    {
        //Error happens here
        messagesQueue.add(message);
    }

Why am I getting this error and what do I need to do to fix it?

Upvotes: 2

Views: 823

Answers (2)

Daniel Bickler
Daniel Bickler

Reputation: 1140

Per PriorityBlockingQueue's javadoc

A priority queue relying on natural ordering also does not permit insertion of non-comparable objects (doing so results in ClassCastException).

Your Message class needs to implement Comparable

class Message implements Comparable<Message> {
    public int compareTo(Message m) {
        int comparisonResult = //comparison logic. 
        return comparisonResult;
    }
}

Per Comparable#compareTo's javadoc, compareTo

Set a negative integer, zero, or a positive integer if this message is less than, equal to, or greater than (respectively) the specified object.

Your other option is to supply a Comparator to PriorityBlockingQueue.

Upvotes: 1

Aubin
Aubin

Reputation: 14873

Javadoc is clear:

public class PriorityBlockingQueue extends AbstractQueue implements BlockingQueue, Serializable

An unbounded blocking queue that uses the same ordering rules as class PriorityQueue and supplies blocking retrieval operations. While this queue is logically unbounded, attempted additions may fail due to resource exhaustion (causing OutOfMemoryError). This class does not permit null elements. A priority queue relying on natural ordering also does not permit insertion of non-comparable objects (doing so results in ClassCastException).

You have to implement the Comparable interface.

class Message implements Comparable<Message> {

   public int compareTo( Message o ) {
      int diff = ...;
      return diff;
   }
}

or implement the Comparator interface and give it to the constructor of PriorityBlockingQueue.

class MyComp implements Comparator<Message> {

   public int compare( Message l, Message r ) {
      int diff = ...;
      return diff;
   }
}

Upvotes: 0

Related Questions