專案常需在 Web 容器中運行長期後台任務(如資料同步、報表生成、訊息推播)。標準 Timer 或 Quartz 皆為「定時觸發」模型,難以滿足以下業務需求:
任務本質是一個受控執行緒,狀態僅有 RUNNING / STOPPED。以 volatile boolean 做開關旗標,while(switch) { doWork(); } 迴圈即可實現啟停控制。
MyTask (extends Thread)
├─ volatile boolean runningFlag
├─ run() // while(runningFlag) { businessLogic(); }
├─ startTask() // CAS 設定 flag=true 並 start()
└─ stopTask() // flag=false,等待 run() 自然結束
TaskExecutor (單例)
├─ synchronized execute() // 確保同一時間僅啟動一個任務執行緒
└─ 持有 MyTask 實例引用
三個極簡 JSP 頁面即可:
index.jsp:顯示狀態,提供「啟動」「關閉」超連結on.jsp:呼叫 MyTask.startTask() + TaskExecutor.execute()off.jsp:呼叫 MyTask.stopTask()public class MyTask extends Thread {
private volatile boolean running = false;
@Override
public void run() {
while (running) {
// 實際業務邏輯
doBusinessWork();
}
System.out.println("任務執行緒已安全結束");
}
public synchronized void startTask() {
if (!running) {
running = true;
this.start(); // 啟動執行緒
}
}
public synchronized void stopTask() {
running = false; // 讓 while 迴圈自然跳出
}
}
public class TaskExecutor {
private static final TaskExecutor INSTANCE = new TaskExecutor();
private MyTask currentTask;
private TaskExecutor() {}
public static TaskExecutor getInstance() { return INSTANCE; }
public synchronized void execute() throws InterruptedException {
if (currentTask != null && currentTask.isAlive()) {
throw new IllegalStateException("任務已在執行中");
}
currentTask = new MyTask();
currentTask.startTask();
// 短暫等待確認執行緒啟動
Thread.sleep(100);
}
}
volatile 保證旗標跨執行緒可見性stopTask() 僅置旗標,不呼叫 deprecated 的 Thread.stop()doBusinessWork() 應可被中斷或具備檢查點,避免長時間阻塞導致關閉等待過久join(timeout) 超時強制中斷機制以 狀態旗標 + 單執行緒迴圈 + 同步控制 為核心,僅百行程式碼即可構建符合業務強控制需求的後台任務執行器。這不僅解決當下問題,更展示「簡單設計」在特定場景下的工程價值。