目录
FutureTask基本介绍
FutureTask 是 Java 并发编程中用于处理异步任务的一个重要类,它实现了 Runnable 和 Future 接口,主要用于异步任务的执行和结果获取。
FutureTask 通过整合任务执行与结果管理,简化了异步编程模型,适用于需灵活控制任务生命周期及获取结果的场景。
FutureTask继承结构
FutureTask → RunnableFuture → Runnable + Future,兼具任务执行和结果管理的双重能力。
应用场景
FutureTask 可以用于以下场景:
- 异步任务执行:可以在后台线程中执行耗时操作,主线程可以继续执行其他任务。
- 结果获取:可以在任务执行后获取结果,支持任务的取消。
- 线程池:可以与 ExecutorService 结合使用,管理异步任务。
示例代码
示例1:
基础线程使用
FutureTask<Integer> task = new FutureTask<>(() -> 1+2);
new Thread(task).start();
Integer result = task.get(); // 阻塞获取结果
FutureTask 可以结合 Callable 或 Runnable 使用。通常情况下,建议使用 Callable 来返回结果。
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.FutureTask;
public class FutureTaskExample {
public static void main(String[] args) {
// 创建一个 Callable 任务
Callable<Integer> callableTask = () -> {
// 模拟长时间的计算
Thread.sleep(2000);
return 42; // 返回计算结果
};
// 创建 FutureTask
FutureTask<Integer> futureTask = new FutureTask<>(callableTask);
// 启动线程来执行 FutureTask
new Thread(futureTask).start();
// 主线程可以做其他工作
System.out.println("主线程正在执行其他操作...");
try {
// 获取计算结果,阻塞直到计算完成
Integer result = futureTask.get();
System.out.println("计算结果: " + result);
} catch (InterruptedException | ExecutionException e) {
e.printStackTrace();
}
}
}
执行结果:
代码说明:
- Callable:定义了一个可以返回结果的任务。
- FutureTask:将 Callable 封装为 FutureTask 对象。
- 线程启动:在新线程中执行 FutureTask。
- 结果获取:通过 futureTask.get() 获取结果,主线程会在此处阻塞,直到任务完成。
示例2:
线程池集成
ExecutorService executor = Executors.newCachedThreadPool();
Future<Integer> future = executor.submit(() -> 1+2);
Integer result = future.get();
ExecutorService executorService = Executors.newCachedThreadPool();
FutureTask<Integer> futureTask = new FutureTask<>(() -> 1+2);
executorService.execute(futureTask);
Integer result = futureTask.get();
通常情况下,FutureTask 不直接使用,而是通过 ExecutorService 来管理。这可以简化线程管理和任务调度。
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.FutureTask;
public class FutureTaskWithExecutorService {
public static void main(String[] args) {
// 创建一个固定大小的线程池
ExecutorService executorService = Executors.newFixedThreadPool(2);
// 定义一个 Callable 任务
Callable<Integer> callableTask = () -> {
Thread.sleep(2000); // 模拟长时间运行的任务
return 42;
};
// 包装 Callable 任务为 FutureTask
FutureTask<Integer> futureTask = new FutureTask<>(callableTask);
// 提交 FutureTask 到 ExecutorService
executorService.execute(futureTask);
try {
// 在任务执行期间可以做其他事情
System.out.println("执行其他工作...");
Integer result = futureTask.get(); // 获取任务结果,阻塞直到完成
System.out.println("结果: " + result);
} catch (InterruptedException | ExecutionException e) {
e.printStackTrace();
} finally {
executorService.shutdown(); // 关闭线程池
}
}
}
执行结果:
代码说明:
- 创建线程池:使用 Executors.newFixedThreadPool(2) 创建一个固定大小的线程池。
- 定义任务:实现 Callable 接口并定义一个返回整数的任务。
- 包装任务:将 Callable 任务包装为 FutureTask 对象。
- 提交任务:使用 executorService.execute(futureTask) 提交 FutureTask 到线程池。
- 获取结果:调用 futureTask.get() 来获取任务的结果,这会阻塞直到任务完成。
- 异常处理:捕获可能的异常,处理任务执行中的错误。
- 关闭线程池:使用 executorService.shutdown() 关闭线程池,避免资源泄漏。
示例3:
虽然 FutureTask 通常与 Callable 一起使用,但它也可以与 Runnable 一起使用。如果任务不需要返回结果,可以使用 Runnable :
import java.util.concurrent.FutureTask;
public class FutureTaskRunnableExample {
public static void main(String[] args) {
Runnable runnableTask = () -> {
System.out.println("正在执行任务...");
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
System.out.println("任务完成!");
};
FutureTask<Void> futureTask = new FutureTask<>(runnableTask, null);
new Thread(futureTask).start();
try {
futureTask.get(); // 等待任务完成
System.out.println("主线程完成!");
} catch (Exception e) {
e.printStackTrace();
}
}
}
执行结果:
总结
FutureTask 是 Java 并发编程中的一个重要工具,是一种有效的异步编程工具,用于处理异步任务。适合用于需要并发执行的任务,能够提高程序的性能和响应速度。通过它,可以轻松地在多线程环境中处理耗时操作,同时保持代码的清晰和可维护性。
FutureTask 通常与 ExecutorService 一起使用,可以高效地管理线程和任务调度。这种组合使得异步编程更加高效和易于管理。