針對 EJB 環境下 Java 序列化效能瓶頸,提供完整可執行的多執行緒壓測程式,支援執行緒數、測試時長、序列化物件大小三大關鍵參數動態調整,並內建執行緒狀態監控與 Thread Dump 觸發機制,助你精準定位序列化熱點。
public class Test implements Runnable {
// 三大可調參數
private static final int THREAD_COUNT = 50; // 並發執行緒數
private static final long TEST_TIME_SECOND = 30; // 測試持續秒數
private static final long ITEMS_COUNT_IN_TEST_OBJECT = 1000; // 序列化物件包含的子項目數
// 線程安全計數器
private static int finishedCount = 0;
private static boolean needStop = false;
private static final Object needStopLock = new Object();
private static final Object finishedCountLock = new Object();
// 序列化測試物件
private static class Data implements Serializable {
private static final long serialVersionUID = -376987039014824563L;
private static final ArrayList DEFAULT = new ArrayList();
static {
for (int i = 0; i < ITEMS_COUNT_IN_TEST_OBJECT; i++)
DEFAULT.add(new DataItem(i));
}
private ArrayList content = DEFAULT;
}
private static class DataItem implements Serializable {
private static final long serialVersionUID = 1L;
private static final String a = "sdfsdfsdfffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff";
private int number; private String content;
public DataItem(int number) { this.number = number; this.content = a + number; }
}
// 主程式:啟動執行緒、計時、停止控制
public static void main(String[] args) {
new Test().test(); // 預熱載入類別
long timeBegin = System.currentTimeMillis();
for (int i = 0; i < THREAD_COUNT; i++) {
Thread t = new Thread(new Test());
t.setName("testthread" + i);
t.start();
}
long timeEnd = timeBegin + TEST_TIME_SECOND * 1000;
while (System.currentTimeMillis() < timeEnd) { Thread.sleep(50); }
setNeedStop();
System.out.println(THREAD_COUNT + " threads finished " + finishedCount + " times in " + TEST_TIME_SECOND + " seconds");
}
public void run() { while (!isNeedStop()) { test(); addFinisedCount(); } }
private void test() {
ByteArrayOutputStream bos = new ByteArrayOutputStream();
Data data = new Data();
try (ObjectOutputStream oos = new ObjectOutputStream(bos)) {
oos.writeObject(data);
bos.toByteArray(); // 觸發序列化
} catch (IOException e) { e.printStackTrace(); }
}
// 同步輔助方法略...
}
| 參數 | 建議範圍 | 影響面向 |
|---|---|---|
| THREAD_COUNT | 10-200 | 並發壓力、CPU 爭用、GC 頻率 |
| TEST_TIME_SECOND | 30-300 | 預熱充分性、穩態效能觀測窗口 |
| ITEMS_COUNT_IN_TEST_OBJECT | 100-10000 | 序列化物件圖深度/廣度、記憶體佔用、輸出位元組大小 |
jstack 或 VisualVM 捕獲執行緒快照,定位阻塞點。test() 中記錄 bos.size() 觀察輸出位元組分佈。包含 Eclipse 專案、Thread Dump 樣本、JProbe 配置:下載連結
ObjectOutputStream 的 writeObject() 耗時分佈,識別異常長尾請求。Externalizable、採用 Protobuf/Kryo 替代、啟用序列化快取、減少物件圖深度。