The Executors
class in Java provides factory methods to create Callable
objects. These methods are useful for wrapping tasks that implement the Runnable
interface or for tasks that return a result. This guide will cover the usage of Executors.callable()
methods, explain how they work, and provide concise examples to demonstrate their functionality in real-world use cases.
Introduction
The Executors.callable()
methods are used to create Callable
objects from various types of tasks, including Runnable
tasks and tasks that return a specific result. These methods provide flexibility in converting tasks to Callable
instances, which can be used with an ExecutorService
for concurrent execution.
Overloaded Methods
1. callable(Runnable task)
This method wraps a Runnable
task into a Callable
that returns null
upon completion.
Syntax
public static Callable<Object> callable(Runnable task)
2. callable(Runnable task, T result)
This method wraps a Runnable
task into a Callable
that returns a specified result upon completion.
Syntax
public static <T> Callable<T> callable(Runnable task, T result)
3. callable(PrivilegedAction<T> action)
This method wraps a PrivilegedAction
task into a Callable
that returns the result of the action.
Syntax
public static <T> Callable<T> callable(PrivilegedAction<T> action)
4. callable(PrivilegedExceptionAction<T> action)
This method wraps a PrivilegedExceptionAction
task into a Callable
that returns the result of the action and can throw checked exceptions.
Syntax
public static <T> Callable<T> callable(PrivilegedExceptionAction<T> action)
Examples
Example 1: Wrapping a Runnable
Task
In this example, we wrap a Runnable
task into a Callable
that returns null
upon completion.
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
public class CallableExample {
public static void main(String[] args) {
ExecutorService executor = Executors.newFixedThreadPool(1);
Runnable task = () -> System.out.println("Executing runnable task");
Callable<Object> callableTask = Executors.callable(task);
Future<Object> future = executor.submit(callableTask);
try {
future.get();
System.out.println("Task completed successfully");
} catch (InterruptedException | ExecutionException e) {
e.printStackTrace();
} finally {
executor.shutdown();
}
}
}
Output:
Executing runnable task
Task completed successfully
Example 2: Wrapping a Runnable
Task with a Result
In this example, we wrap a Runnable
task into a Callable
that returns a specified result upon completion.
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
public class CallableWithResultExample {
public static void main(String[] args) {
ExecutorService executor = Executors.newFixedThreadPool(1);
Runnable task = () -> System.out.println("Executing runnable task with result");
Callable<String> callableTask = Executors.callable(task, "Task result");
Future<String> future = executor.submit(callableTask);
try {
String result = future.get();
System.out.println("Result: " + result);
} catch (InterruptedException | ExecutionException e) {
e.printStackTrace();
} finally {
executor.shutdown();
}
}
}
Output:
Executing runnable task with result
Result: Task result
Example 3: Wrapping a PrivilegedAction
Task
In this example, we wrap a PrivilegedAction
task into a Callable
that returns the result of the action.
import java.security.PrivilegedAction;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
public class PrivilegedActionExample {
public static void main(String[] args) {
ExecutorService executor = Executors.newFixedThreadPool(1);
PrivilegedAction<String> action = () -> "Privileged action result";
Callable<String> callableTask = Executors.callable(action);
Future<String> future = executor.submit(callableTask);
try {
String result = future.get();
System.out.println("Result: " + result);
} catch (InterruptedException | ExecutionException e) {
e.printStackTrace();
} finally {
executor.shutdown();
}
}
}
Output:
Result: Privileged action result
Example 4: Wrapping a PrivilegedExceptionAction
Task
In this example, we wrap a PrivilegedExceptionAction
task into a Callable
that returns the result of the action and can throw checked exceptions.
import java.security.PrivilegedExceptionAction;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
public class PrivilegedExceptionActionExample {
public static void main(String[] args) {
ExecutorService executor = Executors.newFixedThreadPool(1);
PrivilegedExceptionAction<String> action = () -> "Privileged exception action result";
Callable<String> callableTask = Executors.callable(action);
Future<String> future = executor.submit(callableTask);
try {
String result = future.get();
System.out.println("Result: " + result);
} catch (InterruptedException | ExecutionException e) {
e.printStackTrace();
} finally {
executor.shutdown();
}
}
}
Output:
Result: Privileged exception action result
Conclusion
The Executors.callable()
methods in Java are useful for wrapping different types of tasks into Callable
objects. These methods provide flexibility in converting Runnable
, PrivilegedAction
, and PrivilegedExceptionAction
tasks into Callable
instances, making them suitable for concurrent execution with an ExecutorService
.
Comments
Post a Comment
Leave Comment