Java 多線程編程是並發編程的基石。掌握三種核心創建線程方式的本質差異、適用場景與進階用法,是構建高性能並發系統的前置技能。
public class ThreadExtendsThread extends Thread {
private int i;
@Override
public void run() {
for (; i < 100; i++) {
System.out.println(getName() + " " + i);
}
}
}
// 使用方式
ThreadExtendsThread thread = new ThreadExtendsThread();
thread.start(); // 必須調用 start(),而非 run()
特點:
public class ThreadImplementsRunnable implements Runnable {
private int i;
@Override
public void run() {
for (; i < 100; i++) {
System.out.println(Thread.currentThread().getName() + " " + i);
}
}
}
// 使用方式
Runnable runnable = new ThreadImplementsRunnable();
new Thread(runnable).start(); // 線程 1
new Thread(runnable).start(); // 線程 2:共享同一 Runnable 實例字段
特點:
import java.util.concurrent.Callable;
import java.util.concurrent.FutureTask;
public class ThreadImplementsCallable implements Callable<Integer> {
private int i;
@Override
public Integer call() throws Exception {
for (; i < 100; i++) {
System.out.println(Thread.currentThread().getName() + " " + i);
}
return i; // 返回結果
}
}
// 使用方式
Callable<Integer> callable = new ThreadImplementsCallable();
FutureTask<Integer> futureTask = new FutureTask<>(callable);
new Thread(futureTask).start(); // 線程 1
new Thread(futureTask).start(); // 線程 2:共享 FutureTask,結果僅計算一次
// 主線程異步獲取結果
try {
Integer result = futureTask.get(); // 阻塞直到完成
System.out.println("futureTask return: " + result);
} catch (Exception e) {
e.printStackTrace();
}
特點:
future.get()get() 共享結果cancel()、isDone()、isCancelled()、get(timeout)| 維度 | 繼承 Thread | 實現 Runnable | 實現 Callable + FutureTask |
|---|---|---|---|
| 繼承限制 | 受單繼承限制 | 無限制 | 無限制 |
| 返回值 | 無(靜態/字段傳遞) | 無 | ✅ 泛型返回值 |
| 拋檢查異常 | 無 | 無 | ✅ 可拋 Exception |
| 共享狀態 | 各自獨立 | ✅ 同 Runnable 共享字段 | ✅ 同 FutureTask 共享結果 |
| 結果獲取 | 困難 | 困難 | ✅ future.get() 阻塞獲取 |
| 取消控制 | 無 | 無 | ✅ future.cancel() |
| 適用場景 | 簡單獨立任務 | 共享資源任務、線程池提交 | 異步計算、有返回值、需異常處理 |
生產環境不建議顯式 new Thread(),應使用線程池:
ExecutorService executor = Executors.newFixedThreadPool(4); // 提交 Runnable executor.execute(new ThreadImplementsRunnable()); // 提交 Callable,獲取 Future Future<Integer> future = executor.submit(new ThreadImplementsCallable()); Integer result = future.get(); // 阻塞獲取 // 批量提交 List<Future<Integer>> futures = executor.invokeAll(tasks); // 關閉 executor.shutdown();
本質上只有三種創建「線程任務」的方式,但執行方式分為:
new Thread(task).start()(開發/測試)ExecutorService.submit/execute(task)(生產標準)CompletableFuture.supplyAsync(() -> result)(Java 8+ 異步編排)Virtual Thread (Java 21+):Thread.startVirtualThread(() -> {})volatile、AtomicInteger、synchronized 或 ThreadLocalIllegalStateExceptionget(5, TimeUnit.SECONDS) 防止死等future.get() 拋 ExecutionException,真實異常在 getCause()ThreadPoolExecutor 精細控制核心/最大線程、隊列、拒絕策略、存活時間三種方式層層遞進,解決了「如何運行」「任務解耦」「異步結果」三大核心需求,構成了 Java 並發編程的基石三角。