Home > Blockchain >  ThreadPool throws java.util.concurrent.FutureTask cannot be cast to java.lang.Comparable
ThreadPool throws java.util.concurrent.FutureTask cannot be cast to java.lang.Comparable

Time:07-06

I've got a very simple program:

    public static void main(String[] args) throws Exception {
        class MyThread2 implements Runnable{
            @Override
            public void run() {
                while (true) {
                    try {
                        if (Thread.interrupted()) {
                            System.out.println("Terminated!");
                            throw new InterruptedException();
                        }
                    } catch (InterruptedException e) {
                        return;
                    }
                }
            }
        }
        ThreadPoolExecutor executor = new ThreadPoolExecutor(
                2,
                2,
                1,
                TimeUnit.SECONDS,
                new PriorityBlockingQueue<>(),
                Executors.defaultThreadFactory());
        executor.submit(new MyThread2());
        executor.submit(new MyThread2());
        executor.submit(new MyThread2());
        executor.shutdownNow();
    }

On running it using maven, it prints:

[WARNING]
java.lang.ClassCastException: java.util.concurrent.FutureTask cannot be cast to java.lang.Comparable
    at java.util.concurrent.PriorityBlockingQueue.siftUpComparable (PriorityBlockingQueue.java:357)
    at java.util.concurrent.PriorityBlockingQueue.offer (PriorityBlockingQueue.java:489)
    at java.util.concurrent.ThreadPoolExecutor.execute (ThreadPoolExecutor.java:1371)
    at java.util.concurrent.AbstractExecutorService.submit (AbstractExecutorService.java:112)
    at MyThreadFactory.main (MyThreadFactory.java:33)
    at org.codehaus.mojo.exec.ExecJavaMojo$1.run (ExecJavaMojo.java:254)
    at java.lang.Thread.run (Thread.java:748)

And hangs. I don't have any "Comparable" implementation for PriorityBlockingQueue in my program, where does this exception came from?

CodePudding user response:

PriorityBlockingQueue expects comparable elements, which your MyThread2 class fails to provide. So you do have Comparable in your program, but it's an internal thing.

Change your executor to use LinkedBlockingQueue, if you can't provide comparable elements, for example. Or obviously, find a way to "explain" how to compare your tasks that you submit (by implementing Comparable).


Now that I think about it, it would have been very cool if the API could detect that. So if you provide a PriorityBlockingQueue and call submit(new MyThread2()), at compile time, this would have detected and a compile time error raised (saying that MyThread2 is not a Comparable). Unfortunately this is not the case in this API, nor I think it's possible at all.

CodePudding user response:

Exception is thrown, because priority blocking queue doesn't know, how to compare its elements. It does not permit non-comparable objects. You have two options:

  1. Make queue elements implement comparable
  2. Provide comparator for queue in constructor

Checkout PriorityBlocking queue javadoc: https://docs.oracle.com/javase/7/docs/api/java/util/concurrent/PriorityBlockingQueue.html

  • Related