Mastering Java Multithreading Thread Pools, Callable, Future, and Concurrency Utilities
Java multithreading becomes more powerful and efficient when you start using thread pools, Callable, Future, and built-in concurrency utilities. These features help manage multiple threads better, especially in large applications.
What is a Thread Pool?
A Thread Pool is a group of pre-created threads that can be reused to perform tasks. It avoids the overhead of creating a new thread every time and improves performance.
https://images.app.goo.gl/1CkeahkMgjNLhFh88
A thread pool is a group of worker threads managed by the Java runtime that are reused to execute multiple tasks, improving performance and resource management.
Using ExecutorService to Run Multiple Tasks
package ayshriv;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
public class Masteringbackend {
public static void main(String[] args) {
ExecutorService executor = Executors.newFixedThreadPool(2);
executor.submit(() -> System.out.println("Task 1 running"));
executor.submit(() -> System.out.println("Task 2 running"));
executor.submit(() -> System.out.println("Task 3 running"));
executor.shutdown();
}
}
Output:
Task 1 running
Task 2 running
Task 3 running
(Note: Order may vary)
In this above code, we created a thread pool with 2 threads using Executors.newFixedThreadPool(2). We submitted 3 tasks, and the thread pool handles them efficiently using available threads. The third task waits if both threads are busy.
What is Callable and Future in Java?
Callable is like Runnable but returns a result.
Future is used to get the result of a Callable after it’s done.
Callable is like a Runnable but can return a result or throw an exception. Future is used to retrieve the result of the Callable once it's done.
Using Callable and Future
package ayshriv;
import java.util.concurrent.*;
public class MasteringBackend {
public static void main(String[] args) throws Exception {
ExecutorService executor = Executors.newSingleThreadExecutor();
Callable<String> task = () -> {
Thread.sleep(1000);
return "Result from Callable";
};
Future<String> future = executor.submit(task);
System.out.println("Doing other work...");
String result = future.get(); // Waits for Callable to finish
System.out.println("Callable Result: " + result);
executor.shutdown();
}
}
Output:
Doing other work...
Callable Result: Result from Callable
In this above code, we used Callable to return a string result after a delay. While the callable runs in the background, the main thread does other work. The future.get() method waits and fetches the result once the task is complete.
Using Scheduled Executor Service
You can schedule tasks to run after a delay or repeatedly.
Scheduled Executor Service with Delay
package ayshriv;
import java.util.concurrent.*;
public class MasteringBackend {
public static void main(String[] args) throws InterruptedException {
ScheduledExecutorService scheduler = Executors.newScheduledThreadPool(1);
Runnable task = () -> System.out.println("Task executed after delay");
scheduler.schedule(task, 2, TimeUnit.SECONDS);
scheduler.shutdown();
}
}
Output:
Task executed after delay
(Appears after approximately 2 seconds)
In this above code, we used ScheduledExecutorService to schedule a task after 2 seconds. This is useful for reminders, retries, or timeout actions in real-time applications.
Using CountDownLatch
CountDownLatch is a utility that waits until all required tasks are finished before moving forward.
Waiting for 3 Threads to Finish
package ayshriv;
import java.util.concurrent.CountDownLatch;
public class MasteringBackend {
public static void main(String[] args) throws InterruptedException {
CountDownLatch latch = new CountDownLatch(3);
Runnable task = () -> {
System.out.println(Thread.currentThread().getName() + " completed");
latch.countDown();
};
new Thread(task).start();
new Thread(task).start();
new Thread(task).start();
latch.await(); // Wait for all 3 threads
System.out.println("All tasks finished. Proceeding...");
}
}
Output:
Thread-0 completed
Thread-1 completed
Thread-2 completed
All tasks finished. Proceeding...
In this above code, we used CountDownLatch(3) to wait until 3 threads complete their tasks. Only after all threads call countDown(), the main thread resumes and prints the final message.
Using CyclicBarrier
CyclicBarrier allows multiple threads to wait for each other to reach a common barrier point.
A synchronization tool that allows a group of threads to wait for each other to reach a common barrier point before continuing execution.
Threads Sync at Barrier
package ayshriv;
import java.util.concurrent.*;
public class MasteringBackend {
public static void main(String[] args) {
CyclicBarrier barrier = new CyclicBarrier(3, () ->
System.out.println("All threads reached barrier. Running final task."));
Runnable task = () -> {
System.out.println(Thread.currentThread().getName() + " is waiting at barrier");
try {
barrier.await(); // Wait for all threads
} catch (Exception e) {
e.printStackTrace();
}
};
new Thread(task).start();
new Thread(task).start();
new Thread(task).start();
}
}
Output:
Thread-0 is waiting at barrier
Thread-1 is waiting at barrier
Thread-2 is waiting at barrier
All threads reached barrier. Running final task.
In this above code, all 3 threads wait at the barrier. When all threads reach the barrier, the barrier action runs. This is useful in parallel processing where you want all threads to finish a phase together before moving to the next.
Have a great one!!!
Author: Ayush Shrivastava
Thank you for being a part of the community
Before you go:
Whenever you’re ready
There are 4 ways we can help you become a great backend engineer:
- The MB Platform: Join thousands of backend engineers learning backend engineering. Build real-world backend projects, learn from expert-vetted courses and roadmaps, track your learnings and set schedules, and solve backend engineering tasks, exercises, and challenges.
- The MB Academy: The “MB Academy” is a 6-month intensive Advanced Backend Engineering Boot Camp to produce great backend engineers.
- Join Backend Weekly: If you like posts like this, you will absolutely enjoy our exclusive weekly newsletter, sharing exclusive backend engineering resources to help you become a great Backend Engineer.
- Get Backend Jobs: Find over 2,000+ Tailored International Remote Backend Jobs or Reach 50,000+ backend engineers on the #1 Backend Engineering Job Board.
Originally published at https://masteringbackend.com on August 3, 2025.
Top comments (0)