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:
- Make queue elements implement comparable
- Provide comparator for queue in constructor
Checkout PriorityBlocking queue javadoc: https://docs.oracle.com/javase/7/docs/api/java/util/concurrent/PriorityBlockingQueue.html