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

Java Callable 與 Future 非同步任務完整實戰指南

     編輯:Java 相關知識

Callable<V> 與 Future<V> 是 Java 5 引入的非同步計算核心介面,解決 Runnable **無回傳值、無法拋檢查例外** 的限制,配合 ExecutorService 實現任務提交、結果獲取、取消、超時控制。

核心介面對比

特性RunnableCallable<V>
方法簽名void run()V call() throws Exception
回傳值無泛型 V
拋檢查例外不可可
提交後拿到無 (或自行共享物件)Future<V>

Future 關鍵方法

  • get():阻塞等待結果,可拋 InterruptedException, ExecutionException。
  • get(timeout, unit):帶超時,超時拋 TimeoutException。
  • cancel(mayInterruptIfRunning):嘗試取消,true 表示執行中也中斷。
  • isDone() / isCancelled():狀態查詢。

完整範例:三種任務示範

import java.util.concurrent.*;

public class CallableFutureDemo {
    // 1. 立即完成任務
    static class FastTask implements Callable<String> {
        @Override public String call() { return "FastTask done"; }
    }

    // 2. 長時間運行任務 (可中斷)
    static class LongTask implements Callable<String> {
        @Override public String call() throws InterruptedException {
            for (int i = 0; i < 10; i++) {
                System.out.println("LongTask working... " + i);
                Thread.sleep(500);
            }
            return "LongTask finished";
        }
    }

    // 3. 會拋出例外的任務
    static class BadTask implements Callable<String> {
        @Override public String call() { throw new RuntimeException("Intentional error"); }
    }

    public static void main(String[] args) {
        ExecutorService es = Executors.newFixedThreadPool(3);

        // 提交任務
        Future<String> f1 = es.submit(new FastTask());
        Future<String> f2 = es.submit(new LongTask());
        Future<String> f3 = es.submit(new BadTask());

        try {
            // 立即拿結果
            System.out.println("f1: " + f1.get());

            // 等待 2 秒後取消長任務
            Thread.sleep(2000);
            System.out.println("Cancel f2: " + f2.cancel(true)); // true = 中斷執行中線程
            System.out.println("f2 cancelled? " + f2.isCancelled());

            // 取得會拋例外的任務結果
            System.out.println("f3: " + f3.get()); // 拋 ExecutionException 包裝 RuntimeException
        } catch (InterruptedException | ExecutionException e) {
            System.err.println("Task error: " + e.getCause().getMessage());
        } finally {
            es.shutdownNow(); // 關閉線程池
        }
    }
}

執行流程說明


f1: FastTask done
LongTask working... 0
LongTask working... 1
LongTask working... 2
LongTask working... 3
Cancel f2: true
f2 cancelled? true
Task error: Intentional error

進階模式

1. CompletionService — 先完成先處理

ExecutorService es = Executors.newFixedThreadPool(10);
CompletionService<Result> cs = new ExecutorCompletionService<>(es);
for (Task t : tasks) cs.submit(t);
for (int i = 0; i < tasks.size(); i++) {
    Future<Result> f = cs.take(); // 阻塞直到有任務完成
    process(f.get());
}

2. Future 組合 (Java 9+ CompletableFuture)

CompletableFuture<String> f1 = CompletableFuture.supplyAsync(() -> "A");
CompletableFuture<String> f2 = CompletableFuture.supplyAsync(() -> "B");
CompletableFuture<String> combined = f1.thenCombine(f2, (a, b) -> a + b);
System.out.println(combined.join()); // "AB"

最佳實務清單

  • 線程池隔離:不同業務類型使用獨立 ExecutorService,避免互相影響。
  • 有界隊列:new ThreadPoolExecutor(..., new LinkedBlockingQueue<>(1000), ...) 防止 OOM。
  • 超時控制:future.get(5, TimeUnit.SECONDS) 避免無限阻塞。
  • 例外處理:ExecutionException.getCause() 取得真實業務例外。
  • 資源洩漏防護:finally { executor.shutdown(); } 或使用 try-with-resources (Java 19+ ExecutorService 實作 AutoCloseable)。
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved