1. 線程與進程的區別
進程是正在運行程序的實例,線程是進程中的執行單元。主要區別:
- 內存空間:不同進程使用不同的內存空間,同一進程下的線程共享內存空間
- 資源開銷:線程更輕量,線程上下文切換成本比進程上下文切換低
- 通信方式:線程間通信更簡單(共享內存),進程間通信需要特殊機制(IPC)
2. 并發與并行
- 并發(Concurrency):同一時間應對多件事情的能力,多個線程輪流使用CPU資源
- 并行(Parallelism):同一時間動手做多件事情的能力,多核CPU同時執行多個線程
補充:并發是邏輯上的同時發生,并行是物理上的同時發生
3. 創建線程的方式
四種主要方式:
- 繼承Thread類 - 重寫run()方法
- 實現Runnable接口 - 實現run()方法(推薦,避免單繼承限制)
- 實現Callable接口 - 實現call()方法,有返回值
- 線程池創建 - 項目中推薦使用方式
Runnable vs Callable:
- Runnable的run()方法無返回值,Callable的call()方法有返回值
- Callable可以拋出異常,Runnable的異常只能內部處理
- Callable需要配合FutureTask獲取結果
4. run()與start()的區別
- start():啟動線程,由JVM調用run()方法,只能調用一次
- run():封裝線程執行的代碼,可以被調用多次,直接調用run()不會創建新線程
5. 線程狀態及轉換
六種狀態:
- NEW(新建):線程對象創建,未調用start()
- RUNNABLE(可運行):調用start()后,包括就緒和運行狀態
- BLOCKED(阻塞):等待獲取synchronized鎖
- WAITING(等待):調用wait()、join()等方法,無限期等待
- TIMED_WAITING(超時等待):調用sleep()、wait(timeout)等方法
- TERMINATED(終止):線程執行完畢或異常終止
狀態轉換關鍵點:
- 獲取鎖失敗 → BLOCKED狀態
- wait()方法 → WAITING狀態,notify()/notifyAll()喚醒
- sleep()方法 → TIMED_WAITING狀態,時間到自動喚醒
6. 線程執行順序控制
使用join()方法保證順序執行:
T1.start();
T1.join(); // 等待T1執行完
T2.start();
T2.join(); // 等待T2執行完
T3.start();
補充:還可以使用CountDownLatch、CyclicBarrier等同步工具
7. notify()與notifyAll()
- notify():隨機喚醒一個等待的線程
- notifyAll():喚醒所有等待的線程
面試技巧:通常推薦使用notifyAll()避免死鎖風險
8. wait()與sleep()的區別
相同點:
都會讓當前線程暫時放棄CPU使用權,進入阻塞狀態
關鍵區別:
- 歸屬不同:sleep()是Thread的靜態方法,wait()是Object的實例方法
- 鎖的處理:wait()會釋放對象鎖,sleep()不會釋放鎖
- 喚醒方式:wait()可被notify()喚醒,sleep()只能等時間到或被interrupt()
- 使用條件:wait()必須在synchronized塊中使用,sleep()無此限制
9. 停止線程的方法
三種方式:
- 使用標志位:設置boolean變量控制run()方法退出(推薦)
- interrupt()方法:
- 打斷阻塞線程(sleep/wait/join)會拋出InterruptedException
- 打斷正常線程,通過檢查中斷狀態決定是否退出
- stop()方法:已廢棄,不推薦使用
最佳實踐:
// 標志位方式
private volatile boolean running = true;
public void run() {while (running) {// 執行任務}
}// interrupt方式
public void run() {while (!Thread.currentThread().isInterrupted()) {// 執行任務}
}