資料處理、事件監聽、週期性檢查等長時間任務若直接操作 Thread/Runnable,需大量樣板代碼處理同步、異常、資源釋放、優雅停止。本文提供可復用的 Worker 抽象框架,封裝通用邏輯,開發者僅需實作核心業務方法。
public abstract class Worker implements Runnable {
private final Object lock = new Object();
private volatile boolean running = false;
// 1. 準備資源(建構子後、執行緒啟動前呼叫)
protected abstract void prepareWorker() throws Exception;
// 2. 核心工作邏輯(持續被 run() 呼叫)
protected abstract void work() throws Exception;
// 3. 釋放資源(停止前呼叫)
protected abstract void releaseWorker() throws Exception;
// 4. 錯誤處理(work() 拋出異常時回呼)
protected abstract void handleError(Throwable t);
// 5. 執行條件檢查(回傳 false 時 work() 掛起等待)
protected abstract boolean isCondition();
// 6. 等待超時(配合 isCondition 使用)
protected long getTimeout() { return 1000; }
// 執行緒主體
public final void run() {
try { prepareWorker(); } catch (Throwable t) { handleError(t); return; }
synchronized(lock) { running = true; }
try {
while (isRunning()) {
try {
if (isCondition()) work();
else synchronized(lock) { lock.wait(getTimeout()); }
} catch (InterruptedException e) { break; }
catch (Throwable t) { handleError(t); }
}
} finally {
try { releaseWorker(); } catch (Throwable ignored) {}
synchronized(lock) { running = false; lock.notifyAll(); }
}
}
public final boolean isRunning() { synchronized(lock) { return running; } }
public final void halt() { synchronized(lock) { running = false; lock.notifyAll(); } }
public final void broadcast() { synchronized(lock) { lock.notifyAll(); } }
}
| 方法 | 職責 | 備註 |
|---|---|---|
| prepareWorker() | 開啟連線、載入配置、建立 Socket 等阻塞初始化 | 在獨立執行緒執行,不阻塞主線程 |
| work() | 單次業務邏輯(如讀取流、執行 SQL、處理事件) | 可拋出 InterruptedException 以配合停止 |
| releaseWorker() | 關閉連線、釋放鎖、清理狀態 | 類似 finalize() 但確定性呼叫 |
| handleError(Throwable) | 記錄日誌、決定是否 halt() | 預設可記錄後停止任務 |
| isCondition() | 回傳 true 表示可執行 work() | 事件驅動模式下檢查緩衝區非空等條件 |
| halt() | 停止任務,喚醒等待鎖 | 若 work() 中有無法中斷的阻塞 (如 JDBC),需自行擴展中斷邏輯 |
public class WaitedWorker extends Worker {
private final BlockingQueue<Task> queue = new LinkedBlockingQueue<>();
protected void prepareWorker() { /* 初始化資源 */ }
protected void work() throws InterruptedException {
Task task = queue.take(); // 阻塞等待任務
task.execute();
}
protected void releaseWorker() { /* 關閉資源 */ }
protected void handleError(Throwable t) { log.error(t); halt(); }
protected boolean isCondition() { return !queue.isEmpty(); }
public void submit(Task t) { queue.offer(t); broadcast(); }
}
Worker worker = new WaitedWorker();
new Thread(worker).start();
// 稍後提交任務
worker.submit(new Task() { public void execute() { ... } });
// 關閉時
worker.halt(); // 或 Thread.interrupt() 組合
配合 Runtime.addShutdownHook() 實現 JVM 關閉時優雅停止所有 Worker。
Worker 框架將執行緒生命週期、同步、異常、資源管理標準化,開發者專注於 work() 業務邏輯,大幅降低多線程錯誤風險,提升代碼可讀性與維護性。