實時 Java(RTSJ, JSR-1/242)在標準 Java 基礎上增強實時能力:確定性響應外部刺激。硬實時系統絕不允許超過截止時間;軟實時容忍偶發違規。核心在於應用程序控制處理器,避免 JVM 內部競爭進程(GC、JIT、類加載、調度)阻塞關鍵路徑。
javax.realtimejava.lang.Thread,受實時調度器管理。Thread.MAX_PRIORITY)。static Thread assignThread(int priority, Runnable r) {
if (priority <= Thread.MAX_PRIORITY) return new Thread(r);
try {
Scheduler sched = Scheduler.getDefaultScheduler();
PriorityScheduler ps = (PriorityScheduler) sched;
if (priority >= ps.getMinPriority()) {
return new RealtimeThread(null, null, null, null, null, r);
}
} catch (LinkageError e) { /* 非實時 JVM */ }
return new Thread(r); // 回退
}
Class> clazz = Class.forName("javax.realtime.RealtimeThread");
Constructor> ctor = findConstructorAcceptingRunnable(clazz);
return (Thread) ctor.newInstance(null, null, null, null, null, runnable);
提供兩個版本的 ThreadContainer:一個創建 Thread,一個創建 RealtimeThread。打包時根據目標 JVM 選擇對應版本,代碼零異常處理,最乾淨。
RTSJ 為每個線程定義 分配上下文,新對象從當前上下文區域分配。除標準堆外,新增三大區域:
| 區域類型 | 特點 | 回收方式 | 典型用途 |
|---|---|---|---|
| Immortal Memory (永久內存) | 永不回收,生命周期 = JVM | 無 | 靜態初始化器、全局常量、類元數據 |
| Scoped Memory (範圍內存) | 進入範圍時分配,退出時整體回收 | 一次性整體回收,無 GC 干擾 | 請求級緩存、事務上下文、實時線程無 GC 工作區 |
| Physical Memory (物理內存) | 映射特定物理地址/設備內存 | 可配置為範圍或永久 | 設備驅動、共享內存、閃存映射 |
IllegalAssignmentError。NoHeapRealtimeThread (NHRT) 繼承 RealtimeThread,禁止訪問堆對象,因此完全不受 GC 干擾。違規拋 MemoryAccessError。適合最嚴格截止時間的中斷處理、數據采集環節。
AsyncEventHandler (AEH):響應異步/週期事件,由 JVM 共享線程池執行,簡化線程管理。BoundAsyncEventHandler:綁定專用線程,確定性更高。PeriodicTimer(週期觸發)、OneShotTimer、外部中斷、Alarms。| 共享線程 | 可週期 | 可訪問堆 | 可訪問永久 | 可訪問範圍 | 可設置截止時間 | 免 GC 干擾 | |
|---|---|---|---|---|---|---|---|
| Thread | 否 | 否 | 是 | 是 | 否 | 否 | 否 |
| RealtimeThread | 否 | 是 | 是 | 是 | 是 | 是 | 否 |
| NoHeapRealtimeThread | 否 | 是 | 否 | 是 | 是 | 是 | 是 |
| AsyncEventHandler | 是 | 是 | 是 | 是 | 是 | 否 | 否 |
| BoundAsyncEventHandler | 否 | 是 | 是 | 是 | 是 | 否 | 否 |
| NoHeap AEH | 是 | 是 | 否 | 是 | 是 | 否 | 是 |
| NoHeap Bound AEH | 否 | 是 | 否 | 是 | 是 | 否 | 是 |
使用 Scoped Memory 共享事件隊列,NHRT 作為消費者(免 GC),AEH 作為生產者(最高優先級),演示範圍內存自動回收特性。
Producer (Runnable):生成事件 ID,存入範圍內存的 LinkedList(作為 Portal 對象),notify() 消費者。Consumer (Runnable):從 Portal 取隊列,循環 wait() 消費。NoHeapHandler extends AsyncEventHandler:最高優先級,handleAsyncEvent() 中 scopedArea.enter(producer)。NoHeapThread extends NoHeapRealtimeThread:正常優先級,run() 中 scopedArea.enter(consumer)。// 1. 創建範圍內存區域 (20KB)
ScopedMemory scopedArea = new VTMemory(20_000);
// 2. 構建消費者線程 (NHRT)
Consumer consumer = new Consumer();
NoHeapThread consumerThread = new NoHeapThread(
new PriorityParameters(sched.getNormPriority()),
scopedArea, consumer);
// 3. 構建生產者處理器 (AEH, 最高優先級)
Producer producer = new Producer(consumerThread);
AsyncEventHandler handler = new NoHeapHandler(
new PriorityParameters(sched.getMaxPriority()),
scopedArea, producer);
AsyncEvent event = new AsyncEvent();
event.addHandler(handler);
// 4. 啟動消費者線程
consumerThread.start();
// 5. 觸發事件序列
event.fire(); event.fire(); event.fire(); // 有消費者,輸出 1 2 3
consumer.setConsuming = false; // 消費者退出範圍 → 隊列自動回收
event.fire(); event.fire(); // 無消費者,隊列即用即銷毀
consumer.setConsuming = true;
event.fire(); // 新隊列,輸出 6
// 最終輸出:1 2 3 6
事件 4、5 未輸出,因消費者關閉期間生產者創建的隊列隨範圍內存退出而整體回收。這展示了 範圍內存「無 GC、確定性回收、生命周期綁定線程進出」 的核心價值:無需手動清理,無內存洩漏,無 GC 停頓。
| 陷阱 | 現象 | 對策 |
|---|---|---|
| 範圍大小誤估 | 太小 → OOM;太大 → 浪費 | 壓測校準,預留 20-30% 余量 |
| 共享範圍計時敏感 | 線程進出時序微變導致範圍長駐不釋放 | 嚴格控制進出邏輯,避免長駐 |
| 非法賦值/訪問 | IllegalAssignmentError, MemoryAccessError | 靜態分析工具(RATCAT)、代碼評審、單元測試覆蓋內存區域邊界 |
| 類初始化觸發 NHRT 錯誤 | 靜態初始化器在堆分配,NHRT 訪問拋錯 | 關鍵類預初始化,或避免 NHRT 直接觸發新類加載 |
| finalize 導致死鎖/延遲回收 | 範圍回收時調用 finalize 可能創建線程/爭用鎖 | 範圍對象避免實現 finalize,或極簡實現 |
| NHRT 間接被 GC 阻塞 | NHRT 等待鎖,持鎖線程被 GC 搶佔 | 關鍵鎖使用優先級繼承鎖,縮短 GC 限額 |
RTSJ 提供了一套完整的工具箱:RealtimeThread + 範圍內存 + 異步事件處理器,開發者可按需組合,從「僅用實時線程」到「全棧無 GC、確定性調度」平滑演進。掌握分配規則、範圍堆棧、優先級繼承鎖是駕馭實時 Java 的核心鑰匙。