返回

揭秘多线程隐形杀手Callable、Future与FutureTask

后端

前言

大家好,欢迎来到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个数。