我可以推荐以下方法:
- 将应修改表的事件放在“挂起事件”队列上,当事件放在队列上且队列为空时,调用事件调度线程以清空队列中的所有事件并更新表模型。这种优化意味着您不再为收到的每个事件调用事件调度线程,这解决了事件调度线程无法跟上基础事件流的问题。
- 通过使用无状态内部类来排出表面板实现中的挂起事件队列,避免在调用事件调度线程时创建新的 Runnable。
- 可选的进一步优化:清空挂起事件队列时,通过记住需要重新绘制哪些表行,然后在处理所有事件后触发单个事件(或每行一个事件),将触发的表更新事件数降至最低。
示例代码
public class MyStockPanel extends JPanel {
private final BlockingQueue<StockEvent> stockEvents;
// Runnable invoked on event dispatch thread and responsible for applying any
// pending events to the table model.
private final Runnable processEventsRunnable = new Runnable() {
public void run() {
StockEvent evt;
while ((evt = stockEvents.poll() != null) {
// Update table model and fire table event.
// Could optimise here by firing a single table changed event
// when the queue is empty if processing a large #events.
}
}
}
// Called by thread other than event dispatch thread. Adds event to
// "pending" queue ready to be processed.
public void addStockEvent(StockEvent evt) {
stockEvents.add(evt);
// Optimisation 1: Only invoke EDT if the queue was previously empty before
// adding this event. If the size is 0 at this point then the EDT must have
// already been active and removed the event from the queue, and if the size
// is > 0 we know that the EDT must have already been invoked in a previous
// method call but not yet drained the queue (i.e. so no need to invoke it
// again).
if (stockEvents.size() == 1) {
// Optimisation 2: Do not create a new Runnable each time but use a stateless
// inner class to drain the queue and update the table model.
SwingUtilities.invokeLater(processEventsRunnable);
}
}
}