In Java, the ExecutorService
interface is part of the java.util.concurrent
package and provides a higher-level replacement for managing threads and tasks. It simplifies the execution of tasks in a multithreaded environment by abstracting thread creation and management.
Here’s how you can use ExecutorService
to run tasks in Java:
1. Creating an ExecutorService
You can create an instance of ExecutorService
using the factory methods provided by the Executors
class. Some common options are:
- Single-threaded pool:
ExecutorService executor = Executors.newSingleThreadExecutor();
- Fixed-size thread pool:
ExecutorService executor = Executors.newFixedThreadPool(4); // 4 threads in the pool
- Cached thread pool (dynamic sizing):
ExecutorService executor = Executors.newCachedThreadPool();
- Scheduled thread pool (for tasks that need scheduling or delayed execution):
ScheduledExecutorService scheduler = Executors.newScheduledThreadPool(2);
2. Submitting Tasks
You can submit tasks (runnable or callable) to the ExecutorService
for execution:
- Using Runnable:
TheRunnable
interface doesn’t return a result or throw checked exceptions.executor.submit(() -> { System.out.println("Running a task in thread: " + Thread.currentThread().getName()); });
- Using Callable:
TheCallable
interface allows the task to return a result and throw exceptions.Future<Integer> future = executor.submit(() -> { System.out.println("Calculating result in " + Thread.currentThread().getName()); return 42; // returning a result }); // Retrieve the result try { Integer result = future.get(); System.out.println("Result: " + result); } catch (Exception e) { e.printStackTrace(); }
3. Shutting Down the ExecutorService
You need to shut down the ExecutorService
once you’ve completed submitting tasks:
- Graceful shutdown:
This stops accepting new tasks and allows the currently running tasks to complete.executor.shutdown(); try { if (!executor.awaitTermination(60, TimeUnit.SECONDS)) { executor.shutdownNow(); // Force shutdown if timeout happens } } catch (InterruptedException e) { executor.shutdownNow(); }
- Forceful shutdown:
This halts all running tasks and stops new ones immediately.executor.shutdownNow();
4. Example: Submitting Multiple Tasks
package org.kodejava.util.concurrent;
import java.util.concurrent.*;
public class ExecutorServiceExample {
public static void main(String[] args) {
// Create a fixed thread pool with 3 threads
ExecutorService executor = Executors.newFixedThreadPool(3);
// Submit Runnable tasks
for (int i = 0; i < 5; i++) {
final int taskId = i;
executor.submit(() -> {
System.out.println("Task " + taskId + " is running by " + Thread.currentThread().getName());
try {
Thread.sleep(1000); // Simulate work
} catch (InterruptedException e) {
System.err.println("Task " + taskId + " was interrupted!");
}
});
}
// Shutdown the executor gracefully
executor.shutdown();
try {
if (!executor.awaitTermination(60, TimeUnit.SECONDS)) {
executor.shutdownNow(); // Force shutdown if tasks exceed timeout
}
} catch (InterruptedException e) {
executor.shutdownNow();
}
System.out.println("All tasks finished.");
}
}
5. Choosing Between Runnable
and Callable
- Use
Runnable
when your task does not need to return a result. - Use
Callable
when your task needs to return a result or throw checked exceptions.
Advanced Features
If you need to manage periodic tasks or delayed execution, use ScheduledExecutorService
:
ScheduledExecutorService scheduler = Executors.newScheduledThreadPool(2);
// Schedule a task to run after a delay
scheduler.schedule(() -> System.out.println("Task executed after delay"), 3, TimeUnit.SECONDS);
// Schedule a task to run repeatedly at fixed intervals
scheduler.scheduleAtFixedRate(() -> System.out.println("Recurring task"), 1, 5, TimeUnit.SECONDS);
Summary
- Create an
ExecutorService
instance (e.g., fixed thread pool, cached thread pool). - Submit tasks (
Runnable
orCallable
) usingsubmit()
. - Shut down the executor service gracefully (
shutdown()
andawaitTermination()
). - Use
Callable
andFuture
for tasks that need to return results.
This abstraction helps manage your threads efficiently and avoids the complexities of low-level thread creation and management.
- How do I secure servlets with declarative security in web.xml - April 24, 2025
- How do I handle file uploads using Jakarta Servlet 6.0+? - April 23, 2025
- How do I serve static files through a Jakarta Servlet? - April 23, 2025