揭秘多线程隐形杀手Callable、Future与FutureTask
2023-11-26 22:16:20
前言
大家好,欢迎来到Java多线程专题的第二篇——Callable、Future与FutureTask。在上一篇中,我们介绍了多线程的基础知识和概念,以及如何使用Thread类创建和启动线程。在本篇中,我们将深入探讨Callable、Future和FutureTask这三个强大的类,它们将帮助我们编写更加健壮和高效的多线程程序。
Callable
Callable是Java中一个非常重要的接口,它允许我们在线程中执行任务并返回结果。这与Runnable接口不同,Runnable接口只能执行任务,而不能返回结果。Callable接口继承自Runnable接口,因此它既可以执行任务,也可以返回结果。
Callable接口只有一个方法,即call()方法。call()方法接收一个泛型参数,表示任务返回的结果类型。例如,以下代码定义了一个Callable接口,它将返回一个字符串:
public class MyCallable implements Callable<String> {
@Override
public String call() {
// 执行任务并返回结果
return "Hello, world!";
}
}
Future
Future接口代表了一个异步计算的结果。当我们调用Callable接口的call()方法时,Future对象就会被创建。Future对象提供了一个get()方法,它将阻塞线程直到任务完成,然后返回任务的结果。
Future接口还有许多其他有用的方法,例如isDone()方法,它可以判断任务是否已完成;isCancelled()方法,它可以判断任务是否已取消;cancel()方法,它可以取消任务。
FutureTask
FutureTask类是Future接口的一个实现。它可以将Callable对象包装成Runnable对象,这样我们就可以使用ExecutorService来执行Callable任务。
FutureTask类还提供了一些额外的功能,例如设置任务的超时时间。如果任务在超时时间内没有完成,那么任务将被取消。
示例
现在,我们来看一个使用Callable、Future和FutureTask的示例。在这个示例中,我们将创建一个线程池,并使用它来执行一个Callable任务。Callable任务将计算斐波那契数列的前10个数。
import java.util.concurrent.*;
public class Main {
public static void main(String[] args) {
// 创建一个线程池
ExecutorService executorService = Executors.newFixedThreadPool(10);
// 创建一个Callable任务
Callable<List<Integer>> task = () -> {
// 计算斐波那契数列的前10个数
List<Integer> fibonacciNumbers = new ArrayList<>();
int a = 0;
int b = 1;
for (int i = 0; i < 10; i++) {
int c = a + b;
fibonacciNumbers.add(c);
a = b;
b = c;
}
// 返回斐波那契数列
return fibonacciNumbers;
};
// 将Callable任务包装成FutureTask对象
FutureTask<List<Integer>> futureTask = new FutureTask<>(task);
// 使用线程池执行FutureTask对象
executorService.execute(futureTask);
// 等待任务完成
try {
List<Integer> fibonacciNumbers = futureTask.get();
// 打印斐波那契数列
System.out.println(fibonacciNumbers);
} catch (InterruptedException | ExecutionException e) {
e.printStackTrace();
}
// 关闭线程池
executorService.shutdown();
}
}
在这个示例中,我们首先创建了一个线程池。然后,我们创建了一个Callable任务,它将计算斐波那契数列的前10个数。接下来,我们将Callable任务包装成FutureTask对象。最后,我们使用线程池执行FutureTask对象。
一旦FutureTask对象执行完成,我们就可以使用get()方法获取任务的结果。在我们的示例中,我们将斐波那契数列打印到控制台。
总结
在本文中,我们介绍了Callable、Future和FutureTask这三个强大的类。这些类可以帮助我们编写更加健壮和高效的多线程程序。
Callable接口允许我们在线程中执行任务并返回结果。Future接口代表了一个异步计算的结果。FutureTask类是Future接口的一个实现,它可以将Callable对象包装成Runnable对象。
我们还提供了一个示例,演示了如何使用Callable、Future和FutureTask来计算斐波那契数列的前10个数。