Thread.start()(native 方法)啟動新執行路徑run() 只是普通方法調用,不會開啟新線程Thread 本身實現了 Runnable,其 run() 默認空實現public class MyThread extends Thread {
@Override
public void run() {
System.out.println("MyThread.run() 執行於:" + Thread.currentThread().getName());
}
}
// 啟動
new MyThread().start();
優點:寫法簡單,this 即當前線程,獲取名稱/ID 方便。
缺點:Java 單繼承限制,若已有父類則無法使用;任務與執行耦合,難以復用。
public class MyTask implements Runnable {
@Override
public void run() {
System.out.println("MyTask.run() 執行於:" + Thread.currentThread().getName());
}
}
// 啟動:將任務包裝進 Thread
MyTask task = new MyTask();
new Thread(task).start();
// 或提交給線程池
ExecutorService pool = Executors.newFixedThreadPool(3);
pool.submit(task);
優點:
① 避開單繼承限制
② 任務與執行分離,支援線程池、定時任務、CompletableFuture 等高級用法
③ 同一任務實例可提交多次(每次新線程)或共享給多線程(注意線程安全)
// Thread.java 部分源碼
private Runnable target;
public Thread(Runnable target) {
this.target = target;
}
@Override
public void run() {
if (target != null) {
target.run(); // 委派給外部任務
}
}
本質:Thread 是執行載體,Runnable 是業務邏輯載體。
public class MyCallable implements Callable<Integer> {
@Override
public Integer call() throws Exception {
Thread.sleep(1000);
return 42; // 有返回值、可拋異常
}
}
FutureTask<Integer> future = new FutureTask<>(new MyCallable());
new Thread(future).start();
Integer result = future.get(); // 阻塞獲取結果
適用於需要返回值、拋出受檢異常的異步任務。
| 場景 | 推薦方式 | 理由 |
|---|---|---|
| 簡單測試、原型驗證 | extends Thread | 代碼最少 |
| 業務邏輯類已有父類 | implements Runnable | 突破單繼承 |
| 需提交線程池、定時任務 | implements Runnable | 任務解耦 |
| 需獲取返回值/處理異常 | implements Callable | Future 模式支援 |
| Java 8+ 函數式風格 | Lambda/Runnable | () -> { ... } 簡潔 |