Java并发编程(三) FutureTask 的原理与使用

前面两篇文章简单列举了Java 多线程的一些实际场景,但是这两个例子还是过于浅显,仅仅能应对面试官的提问。在后续文章中我们会基于更实战一些的案例来讨论下并发编程。本篇文章使用了大模型进行伪代码和一些特性枚举的生成,本人基于大模型生成的内容做了内容核实和校准,可以放心阅读。

一、引言

在 Java 的并发编程中,我们经常需要在子线程中执行任务并异步获取结果
早期可以通过 ThreadRunnable 来实现并发执行,但它们的缺点是:

  • 无法方便地获取任务执行结果;
  • 无法优雅地处理任务取消、异常、状态管理等。

为了解决这些问题,JDK 1.5 引入了 Future 接口和 FutureTask 类,为异步任务提供了一种标准化的管理方式。


二、Future 与 FutureTask 简介

1. Future 接口

Future<V> 表示一个异步计算的结果,它提供了几个核心方法:

public interface Future<V> {
    boolean cancel(boolean mayInterruptIfRunning);
    boolean isCancelled();
    boolean isDone();
    V get() throws InterruptedException, ExecutionException;
    V get(long timeout, TimeUnit unit)
        throws InterruptedException, ExecutionException, TimeoutException;
}

这些方法允许我们:
• 取消任务(cancel)
• 检查任务状态(isDone、isCancelled)
• 阻塞等待结果(get)


  1. FutureTask 类

FutureTask 是 Future 接口的一个实现类,同时还实现了 Runnable 接口。

也就是说:

一个 FutureTask 既是一个任务(可以被线程或线程池执行),也是一个可获取结果的 Future。

其核心类声明如下:

public class FutureTask<V> implements RunnableFuture<V> {
    // RunnableFuture 继承了 Runnable 和 Future
}

因此,FutureTask 既能提交给 Thread 执行,也能提交给 ExecutorService 管理。


三、FutureTask 的内部原理

FutureTask 内部是通过 状态机 + CAS + LockSupport 实现的异步结果控制。

  1. 状态控制

FutureTask 内部有一个 volatile int state 变量,用于标识任务状态:

状态名 含义
NEW 初始状态,任务未开始
COMPLETING 正在设置结果
NORMAL 执行成功
EXCEPTIONAL 执行抛出异常
CANCELLED 已取消(未执行)
INTERRUPTING 正在中断执行
INTERRUPTED 已中断执行完毕

任务状态通过 CAS 操作原子更新,保证线程安全。

  1. 执行流程

当调用 FutureTask.run() 时,主要流程如下:

public void run() {
    if (state != NEW || !runner.compareAndSet(null, Thread.currentThread()))
        return; // 已执行或其他线程执行中

    try {
        Callable<V> c = callable;
        if (c != null && state == NEW) {
            V result = c.call();          // 执行任务
            set(result);                  // 设置结果
        }
    } catch (Throwable ex) {
        setException(ex);                 // 设置异常
    }
}

核心点:
• 任务执行逻辑由 Callable.call() 实现;
• 执行完成后通过 set(result) 设置结果并唤醒等待的线程;
• 如果抛出异常,则调用 setException(ex)。


  1. 结果等待机制

当主线程调用 get() 时,如果结果未完成,会进入等待状态:

public V get() throws InterruptedException, ExecutionException {
    int s = state;
    if (s <= COMPLETING)
        s = awaitDone(false, 0L); // 阻塞等待
    return report(s);             // 返回结果或抛异常
}

底层使用 LockSupport.park() 让线程阻塞,直到任务完成时调用 LockSupport.unpark() 唤醒。


四、FutureTask 的使用示例

示例一:直接用 Thread 执行 FutureTask

import java.util.concurrent.*;

public class FutureTaskDemo1 {
    public static void main(String[] args) throws Exception {
        Callable<Integer> callable = () -> {
            System.out.println("计算中...");
            Thread.sleep(2000);
            return 42;
        };

        FutureTask<Integer> futureTask = new FutureTask<>(callable);
        Thread thread = new Thread(futureTask);
        thread.start();

        System.out.println("主线程执行其他任务...");
        System.out.println("结果: " + futureTask.get());
    }
}

输出:

主线程执行其他任务...
计算中...
结果: 42


示例二:结合线程池使用

import java.util.concurrent.*;

public class FutureTaskDemo2 {
    public static void main(String[] args) throws Exception {
        ExecutorService executor = Executors.newFixedThreadPool(2);

        FutureTask<String> futureTask = new FutureTask<>(() -> {
            Thread.sleep(1000);
            return "任务完成";
        });

        executor.submit(futureTask);

        // 等待结果
        System.out.println(futureTask.get());

        executor.shutdown();
    }
}

示例三:任务取消与状态判断

FutureTask<Integer> future = new FutureTask<>(() -> {
    Thread.sleep(3000);
    return 10;
});

new Thread(future).start();

Thread.sleep(1000);
boolean cancelled = future.cancel(true);  // 尝试取消
System.out.println("是否取消成功:" + cancelled);
System.out.println("任务是否完成:" + future.isDone());

五、FutureTask 与 CompletableFuture 的关系

自 Java 8 起,CompletableFuture 进一步增强了 FutureTask 的能力,支持:
• 链式回调 (thenApply, thenAccept)
• 异步组合 (thenCombine, allOf)
• 非阻塞结果获取

可以认为:

FutureTask 是基础设施级的 Future 实现,而 CompletableFuture 是它的进化版本。


六、总结

特性 FutureTask
核心接口 实现 RunnableFuture(= Runnable + Future)
功能 异步执行、结果获取、取消、状态控制
内部机制 CAS 状态机 + LockSupport
使用方式 可直接 new Thread(futureTask).start() 或提交给线程池
适用场景 需要精细控制任务生命周期的异步操作
©著作权归作者所有,转载或内容合作请联系作者
【社区内容提示】社区部分内容疑似由AI辅助生成,浏览时请结合常识与多方信息审慎甄别。
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

相关阅读更多精彩内容

友情链接更多精彩内容