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

Java 創建線程三種方式深度對比:Thread 繼承、Runnable、Callable+Future 實戰解析

     編輯:Java 相關知識

三種創建線程方式對比表

維度繼承 Thread實現 RunnableCallable + Future
核心機制子類重寫 run()實現 run(),作為 Thread target實現 call(),返回結果,FutureTask 包裝
返回值無無有 (Future.get())
拋出異常無法拋出受檢異常無法拋出受檢異常可拋出受檢異常
線程控制this 即當前線程Thread.currentThread() 獲取FutureTask 控制執行
繼承限制單繼承,無法 extends 其他類可實現多接口、extends 其他類同 Runnable
資源共享較難實現同一 Runnable 實例可共享數據同 Runnable
適用場景簡單獨立任務多線程賣票、生產者消費者需要結果/異常的異步計算

方式一:繼承 Thread 類


public class ThreadExtendDemo extends Thread {
    private int count = 0;
    
    @Override
    public void run() {
        for (; count < 100; count++) {
            System.out.println(getName() + " : " + count); // getName() 直接可用
        }
    }
    
    public static void main(String[] args) {
        for (int i = 0; i < 100; i++) {
            System.out.println(Thread.currentThread().getName() + " : " + i);
            if (i == 20) {
                new ThreadExtendDemo().start(); // 啟動線程
                new ThreadExtendDemo().start();
            }
        }
    }
}

優點:代碼簡單,`this` 直接操作線程屬性。
缺點:佔用繼承名額,無返回值,異常處理弱。

方式二:實現 Runnable 接口(推薦基礎方式)


public class RunnableDemo implements Runnable {
    private int count = 0; // 共享數據
    
    @Override
    public void run() {
        for (; count < 100; count++) {
            System.out.println(Thread.currentThread().getName() + " : " + count);
        }
    }
    
    public static void main(String[] args) {
        RunnableDemo task = new RunnableDemo(); // 單實例共享 count
        for (int i = 0; i < 100; i++) {
            System.out.println(Thread.currentThread().getName() + " : " + i);
            if (i == 20) {
                new Thread(task, "線程-A").start();
                new Thread(task, "線程-B").start();
            }
        }
    }
}

優點:解耦任務與線程,**同一任務實例可被多線程共享**,支持繼承其他類,體現面向對象分離關注點。
缺點:需 `Thread.currentThread()` 獲取當前線程,無返回值。

方式三:Callable + FutureTask(需要結果的異步任務)


public class CallableDemo implements Callable {
    
    @Override
    public Integer call() throws Exception {
        int sum = 0;
        for (int i = 0; i < 100; i++) {
            System.out.println(Thread.currentThread().getName() + " : " + i);
            sum += i;
        }
        return sum; // 返回結果
    }
    
    public static void main(String[] args) {
        CallableDemo task = new CallableDemo();
        FutureTask future = new FutureTask<>(task); // 包裝
        
        for (int i = 0; i < 100; i++) {
            System.out.println(Thread.currentThread().getName() + " : " + i);
            if (i == 20) {
                new Thread(future, "有返回值線程").start(); // FutureTask 實現 Runnable
            }
        }
        
        try {
            System.out.println("主線程等待結果...");
            Integer result = future.get(); // 阻塞獲取結果
            System.out.println("子線程返回: " + result); // 4950
        } catch (InterruptedException | ExecutionException e) {
            e.printStackTrace();
        }
    }
}

核心類關係**:

Callable → FutureTask (實現 RunnableFuture → Runnable + Future)
                                    ↓
                              Thread(target=FutureTask)
                                    ↓
                              future.get() 獲取 V

進階:線程池中使用 Callable


ExecutorService executor = Executors.newFixedThreadPool(3);

List> futures = new ArrayList<>();
for (int i = 0; i < 10; i++) {
    final int taskId = i;
    futures.add(executor.submit(() -> {
        // 異步計算
        Thread.sleep(100);
        return taskId * 2;
    }));
}

// 收集結果
for (Future f : futures) {
    System.out.println("結果: " + f.get()); // 阻塞直到完成
}

executor.shutdown();

現代替代方案:CompletableFuture (JDK 8+)


// 異步計算鏈
CompletableFuture.supplyAsync(() -> heavyCompute())
    .thenApply(result -> transform(result))
    .thenAccept(System.out::println)
    .exceptionally(ex -> { log.error(ex); return defaultValue; });

// 組合多個異步任務
CompletableFuture.allOf(
    CompletableFuture.supplyAsync(() -> task1()),
    CompletableFuture.supplyAsync(() -> task2())
).join(); // 等待全部完成

選型決策指南

需要返回值或拋受檢異常?
├── 是 → Callable + FutureTask / ExecutorService.submit(Callable)
│         └── JDK 8+ 首選 CompletableFuture (鏈式、組合、異常處理)
└── 否 → 任務需共享數據/狀態?
    ├── 是 → 實現 Runnable (單實例多線程共享)
    └── 否 → 簡單獨立任務?
        ├── 是 → 繼承 Thread / 實現 Runnable 均可
        └── 否 → 複雜線程控制 → 考慮 Thread 子類或線程池

本質總結

  • Thread:線程控制實體(啟動、休眠、中斷、優先級、守護)
  • Runnable:任務邏輯載體(單方法 `run()`,無返回、無受檢異常)
  • Callable:增強任務邏輯(`call()` 有返回、可拋異常)
  • Future:異步結果句柄(`get()` 阻塞、`cancel()` 取消、`isDone()` 狀態)
  • 最佳實踐:業務邏輯實現 `Runnable`/`Callable`,**提交給線程池**執行,不手動 `new Thread()`
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved