I am just testing FutureTask that has two constructors: FutureTask(Callable<V> callable) and FutureTask(Runnable runnable, V result). The first one is ok but I can't understand the second one. How to set the result of task to "V result" parameter? Do you have any example of a FurtureTask with "Runnable and V"(not null) parameter?
Yes, it needs to be mutable, and since it's being accessed from two different threads, we really should use synchronization (or volatile, or java.util.concurrent.locks.Lock) when reading or writing the values. Otherwise you can get code that works fine 99% of the time, but then gives mysterious NullPointerExceptions or worse. Generally I'd prefer to just use Callable, and have it return an immutable object.
"I'm not back." - Bill Harding, Twister
Joined: Jan 29, 2003
Ooo, I would have guessed get() handled the synchronization, blocking until the FutureTask is done. Good warning to think about that.
Joined: Mar 22, 2007
Thanks for your example and comments but I really wonder what is the purpose of "V result" in constructor from the API design point of view. In above example, inner class is using result that is externally declared, and second parameter plays no role. I think FutureTask(Runnable runnable) is sufficient. Do you know why is the constructor designed like that? Is it wrong design?
Joined: Jan 30, 2000
It's designed like that because most of the time you use a Future to get a result, and a Runnable does not return a result, so the only way to get a result with a Runnable is to let the Runnable modify some other object. The design is not incorrect, it does work - but using a Callable seems much more straightforward.
Stan, I may be overstating the need for synchronization here. There definitely is synchronization elsewhere in FutureTask that may be sufficient for what we need. I was concerned because the run() method is necessarily outside that synchronization, so whatever setting is being done to the V instance is unsynchronized. But there should be no concurrent access to V - the only issue is the sequence of events as seen by two different threads. And the synchronization in get() may be sufficient to create a happens-before barrier that separates what happens in run() from what happens afterwards. It's been awhile since I reviewed the exact rules for how that works. I just remember that there are usually loopholes unless you synchronize everything. This may be an exception.
Originally posted by Daesung Park: How to set the result of task to "V result" parameter?
That is not the intent of the constructor. This constructor is used with a non-null result argument if the result of the Future is fixed. If the result is not fixed then you need to pass second argument as null. Additionally, calling Future.run() directly will execute the future in the same thread, not sure why you need a Future if you want sequential processing.