Understanding Callable and Future in Java Concurrency

This article explains how Java's Callable interface and Future objects work together to produce asynchronous results, compares direct FutureTask usage with ExecutorService submission, and demonstrates handling multiple tasks using CompletionService for efficient multithreaded programming.

Java Captain
Java Captain
Java Captain
Understanding Callable and Future in Java Concurrency

The article introduces Callable and Future, describing Callable as a more powerful counterpart to Runnable that can return a result and throw exceptions, while Future provides a way to retrieve the asynchronous computation's outcome.

It presents a basic example using a Callable<Integer> that generates a random number, wrapped in a FutureTask, started in a new thread, and later retrieved with future.get().

Since FutureTask implements both Runnable and Future, it can be executed as a thread and also used to obtain the Callable's return value; this pattern is useful when a time‑consuming result can be computed in parallel and consumed later.

The article then shows a simplified approach using ExecutorService 's submit method, which accepts a Callable and returns a Future, reducing boilerplate code and delegating thread management to the executor.

It notes that ExecutorService (introduced in JDK 5) abstracts thread lifecycle handling, making it the preferred way to launch tasks in modern Java applications.

For executing multiple tasks and collecting their results, the article demonstrates using CompletionService with a cached thread pool, submitting several Callables that return distinct IDs, and retrieving completed results via cs.take().get().

An alternative method—collecting Futures in a list after submitting tasks to the executor—is mentioned but not detailed.

The article emphasizes that CompletionService returns results in the order of task completion, which can improve performance in scenarios like downloading files of varying sizes, whereas iterating over a list of Futures follows the submission order.

Key differences:

1. CompletionService.take() blocks until a completed task is available and removes it from the queue.

2. Collecting Futures in a list typically yields results in the order they were added, potentially causing delays if earlier tasks take longer.

Original Source

Signed-in readers can open the original source through BestHub's protected redirect.

Sign in to view source
Republication Notice

This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactadmin@besthub.devand we will review it promptly.

JavamultithreadingCallableExecutorServiceFuture
Java Captain
Written by

Java Captain

Focused on Java technologies: SSM, the Spring ecosystem, microservices, MySQL, MyCat, clustering, distributed systems, middleware, Linux, networking, multithreading; occasionally covers DevOps tools like Jenkins, Nexus, Docker, ELK; shares practical tech insights and is dedicated to full‑stack Java development.

0 followers
Reader feedback

How this landed with the community

Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.