線程是操作系統調度的基本單位,Java 內置多線程支持是其核心優勢。本文系統覆蓋線程屬性、三種創建方式、同步協作(wait/notify、sleep/interrupt、join)、線程通信(管道流)、守護線程、優先級等核心知識,附帶完整可運行代碼示例。
Thread t = Thread.currentThread();
String name = t.getName(); // 線程名
int priority = t.getPriority(); // 優先級 1-10,默認 5
ThreadGroup group = t.getThreadGroup(); // 線程組
boolean isDaemon = t.isDaemon(); // 是否守護線程
// 修改屬性
t.setName("Worker-1");
t.setPriority(Thread.MAX_PRIORITY);
t.setDaemon(true); // 必須在 start() 前調用
| 屬性 | 說明 |
|---|---|
| 名字 | 默認 "Thread- |
| 優先級 | JVM 搶佔式調度,高優先級優先獲得 CPU,同優先級時間片輪轉 |
| 線程組 | 樹狀結構管理,支持批量中斷、異常處理,現代較少直接使用 |
| 守護線程 | true:父線程結束時 JVM 強制終止子線程(如 GC);false:用戶線程,JVM 等待所有用戶線程結束才退出 |
Thread daemon = new Thread(() -> {
Thread sub = new Thread(() -> {
for (int i = 0; i < 100; i++) System.out.println("Sub: " + i);
});
sub.setDaemon(true); // 子守護
sub.start();
System.out.println("Daemon main end");
});
daemon.start();
// 設置 daemon.setDaemon(true) 會導致 sub 隨主線程結束而終止
class MyThread extends Thread {
@Override public void run() {
for (int i = 0; i < 5; i++) System.out.println("Thread " + getName() + " running");
}
}
new MyThread().start();
class MyRunnable implements Runnable {
@Override public void run() {
for (int i = 0; i < 5; i++) System.out.println("Thread " + Thread.currentThread().getName() + " running");
}
}
new Thread(new MyRunnable()).start();
new Thread(() -> {
for (int i = 0; i < 5; i++) System.out.println("Lambda thread running");
}).start();
| 模式 | Thread 繼承 / 匿名類 | Runnable 實現 |
|---|---|---|
| 對象關係 | 每個線程一個獨立對象 | 可共享同一 Runnable 實例 |
| 同步鎖 | 各自鎖(this 不同) | 共享鎖(同一 Runnable 實例) |
| 適用場景 | 線程間無共享狀態 | 線程間需共享數據/協作 |
// 多對象多線程:每個線程獨立鎖,notify 喚醒各自
MyThread[] threads = new MyThread[3];
for (int i = 0; i < 3; i++) {
threads[i] = new MyThread(); threads[i].start(); threads[i].wait();
}
for (MyThread t : threads) synchronized(t) { t.notify(); }
// 單對象多線程:共享 Runnable 實例,需 notifyAll 喚醒所有
MyRunnable shared = new MyRunnable();
Thread[] ts = new Thread[3];
for (int i = 0; i < 3; i++) { ts[i] = new Thread(shared); ts[i].start(); }
synchronized(shared) { shared.notifyAll(); } // 必須用 notifyAll
NEW -> start() -> RUNNABLE (就緒/運行)
RUNNABLE -> sleep()/wait()/join()/I/O -> BLOCKED/WAITING/TIMED_WAITING
BLOCKED/WAITING -> 鎖釋放/notify/超時 -> RUNNABLE
RUNNABLE -> run() 結束/stop()/異常 -> TERMINATED
六大標準狀態:NEW、RUNNABLE、BLOCKED、WAITING、TIMED_WAITING、TERMINATED。
synchronized(obj) 塊中調用 obj.wait()/notify()wait() 釋放鎖並進入 Wait Set;notify() 隨機喚醒一個;notifyAll() 喚醒全部while(condition) wait(); 防虛假喚醒
Thread.sleep(5000); // 休眠 5 秒,不釋放鎖
// 中斷休眠
Thread t = new Thread(() -> {
try { Thread.sleep(60000); } catch (InterruptedException e) { return; }
});
t.start(); Thread.sleep(500); t.interrupt(); // 拋出 InterruptedException
最佳實踐:捕獲 InterruptedException 後 重新設置中斷標誌 (Thread.currentThread().interrupt()) 或直接返回終止線程。
Thread t = new Thread(() -> { /* 長任務 */ });
t.start();
// 主線程做其他事...
t.join(); // 阻塞直到 t 結束
System.out.println("主線程繼續");
Thread.yield(); // 暫停當前時間片,重新參與調度,不保證立即切換
利用 PipedInputStream/OutputStream 或 PipedReader/Writer 實現線程間字節/字符流通信,底層為環形緩衝區。
PipedOutputStream pos = new PipedOutputStream();
PipedInputStream pis = new PipedInputStream(pos);
// 寫入線程
new Thread(() -> {
try (BufferedReader br = new BufferedReader(new InputStreamReader(System.in))) {
String line;
while (!(line = br.readLine()).equals("end")) {
pos.write(line.getBytes());
}
} finally { pos.close(); }
}).start();
// 讀取線程
new Thread(() -> {
try {
byte[] buf = new byte[1024];
int len;
while ((len = pis.read(buf)) != -1) {
System.out.println("收到: " + new String(buf, 0, len));
}
} finally { pis.close(); }
}).start();
PipedWriter pw = new PipedWriter();
PipedReader pr = new PipedReader(pw);
BufferedWriter bw = new BufferedWriter(pw);
BufferedReader br = new BufferedReader(pr);
// 寫入線程
new Thread(() -> {
try (BufferedReader sysIn = new BufferedReader(new InputStreamReader(System.in))) {
String line;
while (!(line = sysIn.readLine()).equals("end")) {
bw.write(line); bw.newLine(); bw.flush();
}
} catch (IOException e) { e.printStackTrace(); }
}).start();
// 讀取線程
new Thread(() -> {
try {
String line;
while ((line = br.readLine()) != null) {
System.out.println("收到: " + line);
}
} catch (IOException e) { e.printStackTrace(); }
}).start();
class Worker implements Runnable {
private volatile boolean running = true;
@Override public void run() {
while (running && !Thread.currentThread().isInterrupted()) {
// 業務邏輯
try { Thread.sleep(1000); } catch (InterruptedException e) { break; }
}
// 清理資源
}
public void shutdown() { running = false; }
}
// 使用
Worker w = new Worker();
Thread t = new Thread(w);
t.start();
// ... 稍後終止
w.shutdown(); // 或 t.interrupt();
t.join();
核心原則:
volatile boolean 標誌或 interrupt() 發出終止信號InterruptedException 並優雅退出Thread.stop() / suspend() / resume()(已棄用,不安全)| 傳統 API | 現代替代 | 優勢 |
|---|---|---|
| Thread / Runnable | ExecutorService / CompletableFuture | 線程池復用、任務提交解耷、異步組合、異常處理 |
| synchronized / wait/notify | Lock / Condition / Semaphore | 可中斷、超時、公平、多條件、非塊結構 |
| volatile / 手工同步 | Atomic* / LongAdder / ConcurrentHashMap | 無鎖 CAS、高併發計數器、線程安全集合 |
| PipedStream | BlockingQueue / Disruptor / Reactor Streams | 背壓、批量、非阻塞、函數式組合 |
掌握基礎原理是為了正確選型、排查死鎖/活鎖/饑餓、理解框架源碼。生產代碼中,優先使用 java.util.concurrent 高級組件,將同步協作複雜度交給專家級庫,專注業務價值創造。