I've searched a lot but could not find a solutuion to my problem.
I have my own class, BaseTask
, that uses a ThreadPoolExecutor
to handle tasks.
If I don't want prioritization (i.e. using a LinkedBlockingQueue
) this works just fine, but when I try to use a PriorityBlockingQueue
I get ClassCastException
because the ThreadPoolExecutor
wraps my Tasks into a FutureTask
object.
This is obviously OK because the FutureTask
does not implement Comparable
, but how would I go on to solve the priority problem?
I've read that you could override newTaskFor
in ThreadPoolExecutor
, but I can not seem to find this method at all...?
Any suggestions would be much appreciated!
Some code to help:
In my BaseTask
class I have
private static final BlockingQueue<Runnable> sWorkQueue = new PriorityBlockingQueue<Runnable>();
private static final ThreadFactory sThreadFactory = new ThreadFactory() {
private final AtomicInteger mCount = new AtomicInteger(1);
public Thread newThread(Runnable r) {
return new Thread(r, "AsyncTask #" + mCount.getAndIncrement());
}
};
private static final BaseThreadPoolExecutor sExecutor = new BaseThreadPoolExecutor(
1, Integer.MAX_VALUE, 10, TimeUnit.SECONDS, sWorkQueue, sThreadFactory);
private final BaseFutureTask<Result> mFuture;
public BaseTask(int priority) {
mFuture = new BaseFutureTask<Result>(mWorker, priority);
}
public final BaseTask<Params, Progress, Result> execute(Params... params) {
/* Some unimportant code here */
sExecutor.execute(mFuture);
}
In BaseFutureTask
class
@Override
public int compareTo(BaseFutureTask another) {
long diff = this.priority - another.priority;
return Long.signum(diff);
}
In BaseThreadPoolExecutor
class i override the 3 submit
methods...
The constructor in this class gets called, but none of the submit
methods
I will try to explain this problem with a fully functional code. But before diving into the code I would like to explain about PriorityBlockingQueue
PriorityBlockingQueue : PriorityBlockingQueue is an implementation of BlockingQueue. It accepts the tasks along with their priority and submits the task with the highest priority for execution first. If any two tasks have same priority, then we need to provide some custom logic to decide which task goes first.
Now lets get into the code straightaway.
Driver class : This class creates an executor which accepts tasks and later submits them for execution. Here we create two tasks one with LOW priority and the other with HIGH priority. Here we tell the executor to run a MAX of 1 threads and use the PriorityBlockingQueue.
MyTask class : MyTask implements Runnable and accepts priority as an argument in the constructor. When this task runs, it prints a message and then puts the thread to sleep for 1 second.
MyFutureTask class : Since we are using PriorityBlocingQueue for holding our tasks, our tasks must be wrapped inside FutureTask and our implementation of FutureTask must implement Comparable interface. The Comparable interface compares the priority of 2 different tasks and submits the task with the highest priority for execution.
Priority class : Self explanatory Priority class.
Now when we run this example, we get the following output
Even though we submitted the LOW priority first, but HIGH priority task later, but since we are using a PriorityBlockingQueue, an task with a higher priority will execute first.
It looks like they left that out of apache harmony. There is a svn commit log about a year ago fixing the absence of
newTaskFor
. You can probably just override thesubmit
functions in an extendedThreadPoolExecutor
to create an extendedFutureTask
that isComparable
. They are not very long.My solution:
To answer your question: The
newTaskFor()
method is found inThreadPoolExecutor
's superclass,AbstractExecutorService
. You can simply override it inThreadPoolExecutor
, however.}
as you can guess RunWithPriority is an abstract class that is Runnable and has a Integer priority field
You can use these helper classes:
AND
AND this helper method:
AND then use it like this: