前言
顺带回顾学习一下Callable 或 Runnable 任务
Callable 和 Runnable 任务
Callable
和 Runnable
是 Java 中用于定义任务的接口,它们主要用于并发编程,允许任务在独立的线程中运行。
Runnable 任务
Runnable
是一个函数式接口,只包含一个 run()
方法。它不返回任何结果,也不能抛出检查型异常。Runnable
适用于不需要返回结果或不需要抛出检查型异常的简单任务。
@FunctionalInterface
public interface Runnable {
void run();
}
示例:
public class RunnableExample implements Runnable {
@Override
public void run() {
System.out.println("Runnable task is running");
}
public static void main(String[] args) {
RunnableExample runnableTask = new RunnableExample();
Thread thread = new Thread(runnableTask);
thread.start();
}
}
Callable 任务
Callable
是一个泛型接口,只包含一个 call()
方法。它返回一个结果并且可以抛出检查型异常。Callable
适用于需要返回结果或可能抛出异常的复杂任务。
@FunctionalInterface
public interface Callable<V> {
V call() throws Exception;
}
示例:
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 implements Callable<String> {
@Override
public String call() throws Exception {
Thread.sleep(2000); // 模拟长时间的任务
return "Callable task completed";
}
public static void main(String[] args) {
CallableExample callableTask = new CallableExample();
ExecutorService executorService = Executors.newSingleThreadExecutor();
Future<String> future = executorService.submit(callableTask);
try {
String result = future.get();
System.out.println(result);
} catch (InterruptedException | ExecutionException e) {
e.printStackTrace();
}
executorService.shutdown();
}
}
Callable 与 Runnable 的区别
- 返回结果:
Runnable
不返回结果,而Callable
返回结果。 - 异常处理:
Runnable
不能抛出检查型异常,而Callable
可以抛出检查型异常。 - 接口方法:
Runnable
接口的方法是run()
,Callable
接口的方法是call()
。
FutureTask 和 Callable 或 Runnable
FutureTask
提供了一种将 Callable
或 Runnable
任务封装起来的机制。你可以将一个 Callable
或 Runnable
任务传递给 FutureTask
,然后提交给线程池执行。
示例:
import java.util.concurrent.*;
public class FutureTaskExample {
public static void main(String[] args) {
// 使用 Callable 创建一个任务
Callable<String> callableTask = () -> {
Thread.sleep(2000);
return "Callable task completed";
};
// 使用 FutureTask 封装 Callable 任务
FutureTask<String> futureTask = new FutureTask<>(callableTask);
// 创建线程池
ExecutorService executorService = Executors.newSingleThreadExecutor();
// 提交 FutureTask 给线程池执行
executorService.submit(futureTask);
System.out.println("Main thread is doing other work...");
try {
// 获取 FutureTask 执行结果
String result = futureTask.get();
System.out.println("FutureTask result: " + result);
} catch (InterruptedException | ExecutionException e) {
e.printStackTrace();
}
// 关闭线程池
executorService.shutdown();
}
}
总结
- Runnable:适用于不需要返回结果或不抛出检查型异常的简单任务。
- Callable:适用于需要返回结果或可能抛出检查型异常的复杂任务。
- FutureTask:可以封装
Callable
或Runnable
任务,提供任务的异步执行、结果获取和任务取消功能。
通过理解 Callable
和 Runnable
的区别,以及 FutureTask
如何封装这些任务,可以更好地进行并发编程和任务管理。