[concurrency-interest] Why does FutureTask hold reference to the Callable object forever?
Online at stolsvik.com
Fri Jan 25 06:16:58 EST 2008
Tim Peierls wrote:
> (and since you aren't supplied with the arguments of the initial
> Not sure how being supplied with those arguments would help you avoid
> the need for a forwarding wrapper.
You could create the timing and reschedule-behaviour yourself, I
envisioned. It was just one of many tries to get at that stupid
Exception I obviously had in my code, but which STPE happily swallowed
whole all the time.
> I tried using this feature (the decorateTask-methods) to implement
> Exception-catching by wrapping and overriding run(), but didn't
> manage to do it in any way (it hits me now that you could possibly
> proxy it and use the reflection stuff to change visibility of some
> of those private methods to make it possible to invoke them?).
> But such amazing wizardry is not what those methods are meant to
> enable you to do, then?
> If you want to wrap submitted Runnables, why not wrap them *before*
> submission? If you want to encapsulate that behavior in a
> ScheduledExecutorService, you could write a
> RunnableWrappingScheduledExecutorService that forwards to an underlying
> STPE, but wraps any submitted Runnables using a protected method,
> wrap(Runnable) that by default just returns the Runnable itself.
As mentioned, check:
(The synopsis ain't mine - someone changed it.)
There I made a ScheduledThreadPoolExecutorWithExceptionListening.
" However, after hours of banging my head while looking in vain for
appropriate extension-points or listener-registration possibilities, I
finally came up with an (obvious?) extension that simply overrides all
submit-methods by wrapping up the submitted Callable or Runnable in a
new instance of the same, which invokes the run/call in a try-catch, and
runs notification to registered TaskExceptionListeners before throwing
on (which hopefully should preserve contract - any Callables or
Runnables laying in the queue are already "hidden" behind the internal
And all this lard just because afterExecute wasn't made to include the
Exception, but instead swallowing it. The workaround that Doug added
2006-08-18 is still not a part of the javadoc as he suggested, and it
also assumes that get() is idempotent.
See, my point is: when you SCHEDULE a task to be run in the future, or
repeatedly, you don't sit around waiting for the Future. You fire and
forget. And that class in its default setting simply swallows any
badness happening, making bug hunting a nightmare, obviously in
particular if you don't know about this, and don't quite see it coming.
In the TPE, using execute(Runnable), first you get the Exception in
afterExecture, THEN it is thrown on, so that the running Thread dies,
spitting out the Exception on stderr per default. But with STPE,
everything is *completely* different in these regards, even if you
employ that same method.
To furthermore complicate the matter, one have the FutureTask's handling
of "setException" - it doesn't work - there's a bug, it is acknowledged,
a fix is made, and this was in 2006-08-26:
.. Read my description there: there is TWO things: first the obvious
*bug*, but also a lack of some "getException" that could have been used
in a "done()" override since the obvious option is broken. Although, if
get() is idempotent, it would have worked to implement the same
workaround as Doug describes, mentioned above
This set of classes and interfaces are not very straightforward, IMO.
You pretty much HAVE to read the code to understand the workings, and
doing that isn't all that easy with all the different interfaces and
implementations of Callables, Runnables and Futures and whatnots. I
personally feel I know those things now (which for STPE's case amounts
to "don't use!"), but I'm just thinking poor newbies.
More information about the Concurrency-interest