Currently it is legal to call future.get() on a future returned from a call to TaskExecutor.prepare() without first "starting" the prepared task.
If the task is never "started" the call to future.get() will block indefinitely.
Consider making the call to future.get() throw an IllegalStateException in that situation.
Pros:
will never get that indefinite blocking problem - something that is an easy mistake to make, and hard to detect.
Cons:
it may be a valid use case for a parallel thread to block on a call to future.get() PRIOR to the task being started: for example if it wants to be involved in some sort of "gunshot" start. So that would require the future.get() call to be legal.
Perhaps this can be overcome with an alternative mechanism:
1) prepare the task
2) pause the task before starting it (I'm not sure if this is currently legal)
3) start the task
4) consumer calls future.get()
5) unpause the task.
Need to weigh the risks here.