Java并發(fā)編程(三) FutureTask 的原理與使用

前面兩篇文章簡單列舉了Java 多線程的一些實際場景,但是這兩個例子還是過于淺顯,僅僅能應對面試官的提問。在后續(xù)文章中我們會基于更實戰(zhàn)一些的案例來討論下并發(fā)編程。本篇文章使用了大模型進行偽代碼和一些特性枚舉的生成,本人基于大模型生成的內(nèi)容做了內(nèi)容核實和校準,可以放心閱讀。

一、引言

在 Java 的并發(fā)編程中,我們經(jīng)常需要在子線程中執(zhí)行任務并異步獲取結(jié)果。
早期可以通過 ThreadRunnable 來實現(xiàn)并發(fā)執(zhí)行,但它們的缺點是:

  • 無法方便地獲取任務執(zhí)行結(jié)果;
  • 無法優(yōu)雅地處理任務取消、異常、狀態(tài)管理等。

為了解決這些問題,JDK 1.5 引入了 Future 接口和 FutureTask 類,為異步任務提供了一種標準化的管理方式。


二、Future 與 FutureTask 簡介

1. Future 接口

Future<V> 表示一個異步計算的結(jié)果,它提供了幾個核心方法:

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)
? 檢查任務狀態(tài)(isDone、isCancelled)
? 阻塞等待結(jié)果(get)


  1. FutureTask 類

FutureTask 是 Future 接口的一個實現(xiàn)類,同時還實現(xiàn)了 Runnable 接口。

也就是說:

一個 FutureTask 既是一個任務(可以被線程或線程池執(zhí)行),也是一個可獲取結(jié)果的 Future。

其核心類聲明如下:

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

因此,F(xiàn)utureTask 既能提交給 Thread 執(zhí)行,也能提交給 ExecutorService 管理。


三、FutureTask 的內(nèi)部原理

FutureTask 內(nèi)部是通過 狀態(tài)機 + CAS + LockSupport 實現(xiàn)的異步結(jié)果控制。

  1. 狀態(tài)控制

FutureTask 內(nèi)部有一個 volatile int state 變量,用于標識任務狀態(tài):

狀態(tài)名 含義
NEW 初始狀態(tài),任務未開始
COMPLETING 正在設置結(jié)果
NORMAL 執(zhí)行成功
EXCEPTIONAL 執(zhí)行拋出異常
CANCELLED 已取消(未執(zhí)行)
INTERRUPTING 正在中斷執(zhí)行
INTERRUPTED 已中斷執(zhí)行完畢

任務狀態(tài)通過 CAS 操作原子更新,保證線程安全。

?

  1. 執(zhí)行流程

當調(diào)用 FutureTask.run() 時,主要流程如下:

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

    try {
        Callable<V> c = callable;
        if (c != null && state == NEW) {
            V result = c.call();          // 執(zhí)行任務
            set(result);                  // 設置結(jié)果
        }
    } catch (Throwable ex) {
        setException(ex);                 // 設置異常
    }
}

核心點:
? 任務執(zhí)行邏輯由 Callable.call() 實現(xiàn);
? 執(zhí)行完成后通過 set(result) 設置結(jié)果并喚醒等待的線程;
? 如果拋出異常,則調(diào)用 setException(ex)。


  1. 結(jié)果等待機制

當主線程調(diào)用 get() 時,如果結(jié)果未完成,會進入等待狀態(tài):

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

底層使用 LockSupport.park() 讓線程阻塞,直到任務完成時調(diào)用 LockSupport.unpark() 喚醒。


四、FutureTask 的使用示例

示例一:直接用 Thread 執(zhí)行 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("主線程執(zhí)行其他任務...");
        System.out.println("結(jié)果: " + futureTask.get());
    }
}

輸出:

主線程執(zhí)行其他任務...
計算中...
結(jié)果: 42


示例二:結(jié)合線程池使用

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);

        // 等待結(jié)果
        System.out.println(futureTask.get());

        executor.shutdown();
    }
}

示例三:任務取消與狀態(tài)判斷

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 的關(guān)系

自 Java 8 起,CompletableFuture 進一步增強了 FutureTask 的能力,支持:
? 鏈式回調(diào) (thenApply, thenAccept)
? 異步組合 (thenCombine, allOf)
? 非阻塞結(jié)果獲取

可以認為:

FutureTask 是基礎(chǔ)設施級的 Future 實現(xiàn),而 CompletableFuture 是它的進化版本。


六、總結(jié)

特性 FutureTask
核心接口 實現(xiàn) RunnableFuture(= Runnable + Future)
功能 異步執(zhí)行、結(jié)果獲取、取消、狀態(tài)控制
內(nèi)部機制 CAS 狀態(tài)機 + LockSupport
使用方式 可直接 new Thread(futureTask).start() 或提交給線程池
適用場景 需要精細控制任務生命周期的異步操作
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容