Eclipse 基於 SWT 的原生線程模型要求所有 UI 操作必須在 UI 線程 (創建 Display 的線程) 執行,長耗時任務必須轉至後台線程。Eclipse 提供 Job、UIJob、IProgressService 等高級 API 封裝線程協調、進度報告、取消機制,本文系統講解核心概念與實戰模式。
public static void main(String[] args) {
Display display = new Display();
Shell shell = new Shell(display);
shell.open();
// 事件循環
while (!shell.isDisposed()) {
if (!display.readAndDispatch()) display.sleep();
}
display.dispose();
}
Display 的線程 (通常是 main)。setText、addListener、佈局) 必須在 UI 線程,否則拋 SWTException: Invalid thread access。Job job = new Job("My Background Job") {
@Override
protected IStatus run(IProgressMonitor monitor) {
System.out.println("Running in background thread");
// 耗時操作...
monitor.worked(10); // 進度更新
return Status.OK_STATUS;
}
};
job.setPriority(Job.SHORT); // 優先級: SHORT, LONG, DECORATE, BUILD
job.schedule(); // 盡快啟動
IProgressMonitor 支援 worked()、subTask()、isCanceled() (用戶點擊取消)。monitor.isCanceled() 返回 Status.CANCEL_STATUS。job.addJobChangeListener(new JobChangeAdapter() { public void done(IJobChangeEvent e) { ... } }) 獲取完成通知。job.setSystem(true) 後台靜默運行;setUser(true) 顯示進度對話框,用戶可選「後台運行」。job.schedule(60000) 延遲 60s;schedule(0) 立即。job.join() 阻塞當前線程直到 Job 完成,配合 job.getResult() 獲取狀態。job.schedule();
System.out.println("After schedule");
// 輸出順序不確定:可能先打印 "Running..." 也可能先打印 "After schedule"
使用 join() 可強制同步。
| 方式 | API | 特點 |
|---|---|---|
| 同步阻塞 | Display.syncExec(Runnable) | 當前線程阻塞直到 UI 線程執行完 Runnable,適合需即時結果場景 |
| 異步非阻塞 | Display.asyncExec(Runnable) | 當前線程繼續,Runnable 排隊在 UI 線程執行,最常用 |
| 專用 Job | UIJob (覆寫 runInUIThread) | 本質是 asyncExec 封裝,自帶 Job 生命周期管理 (優先級、取消、監聽) |
UIJob uiJob = new UIJob("Update Label") {
@Override
public IStatus runInUIThread(IProgressMonitor monitor) {
label.setText("Updated from background"); // 直接操作 UI
return Status.OK_STATUS;
}
};
uiJob.schedule();
IProgressService service = PlatformUI.getWorkbench().getProgressService();
service.busyCursorWhile(new IRunnableWithProgress() {
@Override
public void run(IProgressMonitor monitor) {
// 非 UI 耗時操作
}
});

service.runInUI(
PlatformUI.getWorkbench().getProgressService(),
new IRunnableWithProgress() {
@Override
public void run(IProgressMonitor monitor) {
// 可安全操作 UI (如彈出對話框、修改編輯器)
}
},
Platform.getWorkspace().getRoot() // 鎖定資源範圍
);

Job job = new Job("Silent Job") { ... };
job.setUser(false); // 關鍵:非用戶級,不彈進度框
job.schedule();
核心原則:UI 線程只做 UI,耗時操作全扔 Job。善用
asyncExec/UIJob回主線程更新界面,利用IProgressService提供統一進度體驗,遵循 Eclipse 線程模型即可構建流暢、健壯的 RCP 應用。