TML TML - 4 months ago 20
Java Question

ScheduledThreadPoolExecutor afterExecute's runnable.toString is different

I am relatively new to

ThreadPoolExecutor
. I'm seeing if I can track the runnable before being executed and in afterExecute.

By getting
runnable.toString()
using
afterExecute(Runnable t, Throwable t)
. Now, I realize I could just put a Log inside the runnable itself... but I was curious what this method would produce.

For
ThreadPoolExecutor
, works fine,
runnable.toString
is the same before
execute(runnable)
and also in
afterExecute()
.

However!
ScheduledThreadPoolExecutor
is different. Its afterExecute's runnable.toString is quite different.

For example, before:
my.pkg.name@abc
, afterExecute:
java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask@zxc


Not even the pkg name is the same.
Why is this?

private MyThreadPool() {
threadPool = new ThreadPoolExecutor(NUMBER_OF_CORES, MAX_CORES,
KEEP_ALIVE_TIME, KEEP_ALIVE_TIME_UNIT, workQueue) {
@Override
public void afterExecute(Runnable r, Throwable t) {
super.afterExecute(r, t);
Log.d(TAG, "ThreadOps onDone: " + r.toString());
// (A) will return same --> mypkgname@abc
}
};
threadPool.setRejectedExecutionHandler(rejectedHandler);

scheduledThreadPool = new ScheduledThreadPoolExecutor(NUMBER_OF_CORES) {
@Override
public void afterExecute(Runnable r, Throwable t) {
super.afterExecute(r, t);
Log.d(TAG, "ThreadOps onDelayDone: " + r.toString());
// (D) does not return same?
// I am expecting --> mypkgname@qwe , but get...
// java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask@zxc
}
};
scheduledThreadPool.setRejectedExecutionHandler(rejectedHandler);
}

public void execute(Runnable runnable) {
Log.d(TAG, "ThreadOps exe: " + runnable.toString());
// (A) lets say toString --> mypkgname@abc
threadPool.execute(runnable);
}

public void delayExecute(Runnable runnable, long delayms) {
Log.d(TAG, "ThreadOps exe @" + delayms + ": " + runnable.toString());
// (D) lets say toString --> mypkgname@qwe
scheduledThreadPool.schedule(runnable, delayms, TimeUnit.MILLISECONDS);
}

Answer

ScheduledThreadPoolExecutor internally maintains a heap of sorts to easily add and retrieve submitted tasks based on their scheduled (ie. the one that needs to be executed next at the top of the heap).

To help accessing this heap, the implementation of ScheduledThreadPoolExecutor decorates the Runnable or Callable instances you schedule with a custom implementation that describes its position in the heap, among other things. That's the ScheduledFutureTask you see in your logs. Note that this is an implementation detail (it's a private class) and you shouldn't rely on it.