So how FutureTask is an asynchronous computation does it create thread internally and submit the task that we give it at the time of instantiating FutureTask like:
FutureTask
is not designed to be used directly by the user. It is designed to be used through the ExecutorService
interface and the classes that implement it. It is those classes that use FutureTask
and fork the threads, etc.. You may need to read more information about how to use the ExecutorService
concurrency classes.
The ThreadPoolExecutor
class is the main one that actually does the management of the threads in the pool. Typically you call Executors.newCachedThreadPool()
or Executors.newFixedThreadPool(10)
to get an instance of it.
// create a thread pool with 10 workers
ExecutorService threadPool = Executors.newFixedThreadPool(10);
// define your jobs somehow
for (MyCallable job : jobsToDo) {
// under the covers this creates a FutureTask instance
Future future = threadPool.submit(job);
// save the future if necessary in a collection or something
}
// once we have submitted all jobs to the thread pool, it should be shutdown
threadPool.shutdown();
// now we can go back and call `future.get()` to get the results from our jobs
From an academic standpoint, under the covers TPE extends AbstractExecutorService
and it is there that you can see the FutureTask
class being used to manage the tasks in the thread-pool:
public <T> Future<T> submit(Callable<T> task) {
if (task == null) throw new NullPointerException();
RunnableFuture<T> ftask = newTaskFor(task);
execute(ftask);
return ftask;
}
...
protected <T> RunnableFuture<T> newTaskFor(Callable<T> callable) {
return new FutureTask<T>(callable);
}
The code inside of TPE is pretty complicated and it's not easy to show a "snippet" that performs the asynchronous calls. The TPE sees if it needs to add more threads to the pool. submits it to a task queue which can either reject it or accept it, and then the threads dequeue the task and run them in the background.