線程優先級 (`Thread.setPriority(1~10)`) 是「建議」而非「命令」,受 OS 調度器、JVM 實作、CPU 核心數影響極大。本文提供可視化 Swing 演示程式,並揭露優先級在鎖競爭、I/O、虛擬機器環境下的失效場景。
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
public class ThreadPriorityDemo extends JFrame {
private static final int THREAD_COUNT = 10;
private final CounterThread[] threads = new CounterThread[THREAD_COUNT];
private final JPanel panel = new JPanel(new GridLayout(THREAD_COUNT, 1));
public ThreadPriorityDemo() {
super("線程優先級可視化演示");
setDefaultCloseOperation(EXIT_ON_CLOSE);
setLayout(new BorderLayout());
// 建立 10 個優先級 1~10 的計數執行緒
for (int i = 0; i < THREAD_COUNT; i++) {
threads[i] = new CounterThread(i + 1);
panel.add(threads[i].getUI());
}
add(new JScrollPane(panel), BorderLayout.CENTER);
JPanel ctrl = new JPanel();
JButton start = new JButton("全部啟動");
JButton stop = new JButton("全部停止");
start.addActionListener(e -> { for (CounterThread t : threads) t.start(); });
stop.addActionListener(e -> { for (CounterThread t : threads) t.stopThread(); });
ctrl.add(start); ctrl.add(stop);
add(ctrl, BorderLayout.NORTH);
setSize(400, 600);
setLocationRelativeTo(null);
setVisible(true);
}
static class CounterThread extends Thread {
private final JTextField counter = new JTextField(10);
private final JLabel label;
private volatile boolean running = true;
CounterThread(int priority) {
setPriority(priority);
label = new JLabel("優先級: " + priority);
counter.setEditable(false);
}
JPanel getUI() {
JPanel p = new JPanel(new FlowLayout(FlowLayout.LEFT));
p.add(label); p.add(counter);
return p;
}
void stopThread() { running = false; }
@Override
public void run() {
long count = 0;
while (running) {
counter.setText(String.valueOf(++count));
try { sleep(1); } catch (InterruptedException ignored) {}
}
}
}
public static void main(String[] args) {
SwingUtilities.invokeLater(ThreadPriorityDemo::new);
}
}
| 場景 | 原因 | 對策 |
|---|---|---|
| 鎖競爭 | 持有鎖的低優先級線程阻塞高優先級,**優先級反轉** | 用 `ReentrantLock` 公平鎖、縮小臨界區、避免鎖中調用慢操作 |
| I/O 阻塞 | 進入內核態等待 I/O,CPU 調度器不看優先級 | 改用 NIO/非同步 I/O、CompletableFuture |
| CPU 密集 + 核心數足夠 | 所有線程都能獲得核心,優先級差異被稀釋 | 綁定關鍵線程至專用核心 (`taskset`/`cpuset`) |
| 容器/Cgroups | CFS 配額 (cpu.cfs_quota_us) 硬限制,優先級被忽略 | 調整 `cpu.shares` (相對權重) 而非線程優先級 |
理解優先級是「建議」而非「控制」,結合可視化驗證與生產監控,才能在併發系統中做出正確的架構決策。