I have a singleThreadExecutor in order to execute the tasks I submit to it in serial order i.e. one task after another, no parallel execution.
I have runnable which goes something like this
MyRunnable implements Runnable {
@Override
public void run() {
try {
Thread.sleep(30000);
} catch (InterruptedException e1) {
e1.printStackTrace();
}
}
When I submit ,for example, three instances of MyRunnable to the afore-mentioned single thread executor, I would expect to have the first task executing and because of the Thread.sleep has Its executing thread in TIMED_WAITING (I may be wrong about the specific state). The other two tasks should not have threads assigned to execute them, at least not until the first task has finished.
So my question is how to get this state via the FutureTask API or somehow get to the thread that is executing the task (if there is no such thread then the task is waiting to be executed or pending) and get Its state or perhaps by some other means?
FutureTask only defines isCanceled() and isDone() methods, but those are not quite enough to describe all the possible execution statuses of the Task.
If you wanted to be really thorough,
FutureTask
keeps track of statesREADY
,RUNNING
,RAN
, andCANCELLED
internally. You could create a copy of this class and add an accessor for the state. Then overrideAbstractExecutorService.newTaskFor(Runnable)
to wrap it using yourCustomFutureTask
(the inner class isprivate
, so just subclassing won't work).The default implementation of
newTaskFor(Runnable)
is really simple:so it wouldn't be a big deal to override it.
You could wrap anything you submit to this service in a
Runnable
that records when its run method is entered.You could add a
getThread()
method toMyRunnable
that produces theThread
executing therun()
method.I would suggest adding an instance variable like this (must be volatile to ensure correctness):
Do this before the
try
block:And add a
finally
block with this:Then you could call:
for some
MyRunnable
.null
is an ambiguous result at this point, meaning either, "hasn't run," or "has completed." Simply add a method that tells whether the operation has completed:Of course, you'll need an instance variable to record this state:
And set it to true in the
finally
block (probably before setting the thread tonull
, there's a bit of a race condition there because there are two values capturing the state of one thing. In particular, with this approach you could observeisDone() == true
andgetThread() != null
. You could mitigate this by having alock
object for state transitions and synchronize on it when changing one or both state variables):Note that there still isn't any guard that prohibits a single
MyRunnable
from being submitted concurrently to two or more threads. I know you say that you're not doing this... today :) Multiple concurrent executions will lead to corrupted state with high likelihood. You could put some mutual exclusive guard (such as simply writingsynchronized
on therun()
method) at the beginning of the run method to ensure that only a single execution is happening at any given time.Since FutureTask requires a callable object, we will create a simple Callable implementation.
Here is an example of FutureTask method and it’s showing commonly used methods of FutureTask.