|
Description
|
FULL PRODUCT VERSION :
java version "1.6.0"
Java(TM) SE Runtime Environment (build 1.6.0-b105)
Java HotSpot(TM) Client VM (build 1.6.0-b105, mixed mode, sharing)
ADDITIONAL OS VERSION INFORMATION :
customer Windows XP [Version 5.1.2600]
A DESCRIPTION OF THE PROBLEM :
ClassCastException trying to cast FutureTask to Comparable within the offer() method of PriorityQueue
This occurs when using a ThreadPool and a PriorityBlockingQueue such that the maximum threads are filled and the next submitted thread must be added to the queue.
STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
Run the attached application. see stack trace.
EXPECTED VERSUS ACTUAL BEHAVIOR :
EXPECTED -
Expected new Callable objects to be added to the queue (and sorted by priority using the compareTo method of the Callable customer , assuming it has one) and executed by the thread pool when threads become available.
ACTUAL -
ClassCastException
ERROR MESSAGES/STACK TRACES THAT OCCUR :
from thread with text: 1 this array has many more elements
from thread with text: 2 and we want to test it
from thread with text: 3 with many strings
from thread with text: 4 and some more
from thread with text: 5 how many are there
java.lang.ClassCastException: java.util.concurrent.FutureTask
at java.util.PriorityQueue.fixUp(PriorityQueue.java:536)
at java.util.PriorityQueue.offer(PriorityQueue.java:304)
at java.util.concurrent.PriorityBlockingQueue.offer(PriorityBlockingQueue.java:156)
at java.util.concurrent.ThreadPoolExecutor.execute(ThreadPoolExecutor.java:861)
at java.util.concurrent.AbstractExecutorService.submit(AbstractExecutorService.java:45)
at TestJavaBug.test(TestJavaBug.java:54)
at TestJavaBug.main(TestJavaBug.java:33)
java.lang.ClassCastException: java.util.concurrent.FutureTask
at java.util.PriorityQueue.fixUp(PriorityQueue.java:536)
at java.util.PriorityQueue.offer(PriorityQueue.java:304)
at java.util.concurrent.PriorityBlockingQueue.offer(PriorityBlockingQueue.java:156)
....
java.util.concurrent.ThreadPoolExecutor.getTask(ThreadPoolExecutor.java:470)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:674)
at java.lang.Thread.run(Thread.java:595)
from thread with text: 7 or thirty
OKOKOKOKOKOK
REPRODUCIBILITY :
This bug can be reproduced always.
---------- BEGIN SOURCE ----------
import java.util.concurrent.*;
public class TestJavaBug {
private static String[] arr3 = {"1 this array has many more elements",
"2 and we want to test it",
"3 with many strings",
"4 and some more",
"5 how many are there",
"6 twenty is fine",
"7 or thirty",
"8 maybe fourty",
"9 today is Monday",
"10 the month is March",
"11 Loquendo rules!",
"12 something",
"13 something",
"14 something",
"15 something",
"16 something",
"17 something",
"18 something",
"19 something",
"20 something",
"21 something",
"22 something",
"23 done"};
public static void main(String args[])
{
TestJavaBug t = new TestJavaBug();
t.test();
}
public TestJavaBug() {
}
public void test() {
PriorityBlockingQueue q = new PriorityBlockingQueue();
ExecutorService executor = new ThreadPoolExecutor(5, 5, 120, TimeUnit.SECONDS, q);
String[] input = arr3;
for (int i=0; i<input.length; i++) {
try {
String text = input[i];
//int priority = i%2;
int priority = 1;
if (i > 15) priority = 0;
CallableSomething callSome = new CallableSomething(text, priority);
executor.submit(callSome);
} catch (Exception ex) {
ex.printStackTrace();
}
}
try {
executor.awaitTermination(5, TimeUnit.SECONDS);
System.out.println("OKOKOKOKOKOK");
executor.shutdown();
} catch (InterruptedException ex) {
ex.printStackTrace();
}
}
private class CallableSomething implements Callable, Comparable {
private String theText;
private int thePriority;
public CallableSomething(String text, int priority) {
theText = text;
thePriority = priority;
}
public String call() {
String retval = null;
System.out.println("from thread with text: " + theText);
// imagine we do some real work here, setting the string on success
try {
Thread.sleep(2000);
retval = theText;
} catch (InterruptedException ex) {
ex.printStackTrace();
}
return retval;
}
public int compareTo(Object obj) {
int retval = Integer.valueOf(thePriority).compareTo(Integer.valueOf(((CallableSomething)obj).getPriority()));
System.out.println(thePriority + " compareTo " + ((CallableSomething)obj).getPriority() + " retval: " + retval);
return retval;
}
public int getPriority() {
return thePriority;
}
}
}
---------- END SOURCE ----------
CUSTOMER SUBMITTED WORKAROUND :
I copied AbstractExecutorService to my own source file MyAbstractExecutorService and modified the submit() methods to create MyFutureTask instead of FutureTask instances
MyFutureTask extends FutureTask implements Comparable
I then copied ThreadPoolExecutor to MyThreadPoolExecutor which extends MyAbsractExecutorService
Posted Date : 2007-03-28 11:21:19.0
|
|
Comments
|
Submitted On 14-JUN-2007
actually, I think the problem is different. Look carefully - he initializes the ThreadPoolExecutor with PriorityBlockingQueue. Which means that all its elements must be Comparable (or you need to provide a comparator). I bet java.util.concurrent.FutureTask does not implement Comparable.
Submitted On 11-NOV-2007
there is no bug, newTaskFor is protected for a reason, you can close the bug report.
The BlockingQueue might require any fancy interfaces, FutureTask, whatsoever.
Submitted On 11-NOV-2007
p.s extends ThreadPoolExecutor and override newTaskFor. It's an intended workaround.
Submitted On 19-AUG-2009
Gaurav.Mehta
As far as i see PriorityQueue gives the above exception when callable objects implements Comparable and not comparator. But when i tried comparator there was not effect of priority on the execution. Is this also a part of Bug or it was not expected.
PLEASE NOTE: JDK6 is formerly known as Project Mustang
|