javaexceptionqueuethreadpoolcomparable

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


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?


Solution

  • 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.