首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> Java 程式設計 >> Java 相關知識

Java 多線程 FutureTask 實戰:異步預加載、結果緩存、超時控制完整指南

     編輯:Java 相關知識

FutureTask 實現了 Future 和 Runnable,是「異步計算+結果獲取」的核心工具。本文通過預加載場景演示其核心用法,並延伸超時、取消、異常處理最佳實踐。

一、 核心場景:啟動時異步預加載

public class DataPreloader {
    private final FutureTask<List<String>> future = new FutureTask<>(() -> {
        Thread.sleep(10000); // 模擬耗時加載
        return IntStream.range(0, 10).mapToObj(i -> "data" + i).collect(Collectors.toList());
    });
    private final Thread loaderThread = new Thread(future, "DataPreloader");

    public void start() { loaderThread.start(); }

    public List<String> getData() throws InterruptedException, ExecutionException {
        return future.get(); // 計算完成直接返回,否則阻塞等待
    }

    public List<String> getData(long timeout, TimeUnit unit) 
            throws InterruptedException, ExecutionException, TimeoutException {
        return future.get(timeout, unit); // 支援超時控制
    }

    public boolean cancel(boolean mayInterrupt) { return future.cancel(mayInterrupt); }
    public boolean isDone() { return future.isDone(); }
}

二、 關鍵特性與 API

方法說明
get()阻塞直到完成,返回結果或拋出 ExecutionException
get(timeout, unit)超時拋出 TimeoutException,不阻塞無限期
cancel(true)嘗試中斷執行中的任務(需任務響應 interrupt)
isDone()非阻塞檢查是否完成(含正常/異常/取消)
run()實現 Runnable,可直接提交給 Executor

三、 進階模式

  • 結果緩存:FutureTask 內部天然緩存結果,多次 get() 只計算一次。
  • 併發去重:ConcurrentHashMap<Key, FutureTask<Value>> 實現「相同 Key 只加載一次」模式。
  • 組合 CompletableFuture:JDK 8+ 推薦用 CompletableFuture.supplyAsync() 替代,支援鏈式回調、組合、異常處理更強。

四、 避坑指南

  • 任務代碼必須響應 Thread.interrupt(),否則 cancel(true) 無效。
  • get() 會拋出 ExecutionException 包裝真實異常,需 getCause() 獲取根因。
  • 不要在 UI 線程調用無超時 get(),導致界面凍結。

五、 總結

FutureTask 是「畂步計算句柄」的標準實現,適用於「提前觸發、稍後獲取」場景。現代代碼優先選 CompletableFuture,但理解 FutureTask 原理對掌握 JDK 併發包基石至關重要。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved