我有一个程序可以从 Web 解析 XML,然后以 JTable 的形式显示信息。程序运行时可以更新信息。
此更新方法由 EDT 每 X 秒由 Timer 调用,或由用户通过单击刷新按钮调用。
private void updateInfo(int id) {
SwingWorker<ArrayList<Information>, Void> sw = new SwingWorker<>() {
@Override
protected ArrayList<Information> doInBackground() {
return loadInfo(id);
}
@Override
protected void done() {
try {
info = get();
gui.addInfoToTable(formatInfo(info));
} catch (InterruptedException e) {
e.printStackTrace();
} catch (ExecutionException e) {
e.printStackTrace();
}
}
};
sw.execute();
}
doInBackground() 的返回被保存以info
允许用户通过单击 JTable 中的特定单元格来查看特定信息对象的详细信息
没错,如果我尝试通过数百个同时更新对程序进行压力测试,我会得到 ArrayIndexOutOfBoundsException。
据我了解,这是因为某些 doInBackground() 在 done() 之前完成,对吗?
使我的程序线程安全的最简单方法是什么?
更新时访问信息元素会导致任何问题吗?
例外:
Exception in thread "AWT-EventQueue-0" java.lang.ArrayIndexOutOfBoundsException: Index -1 out of bounds for length 10
at java.base/java.util.Vector.elementData(Vector.java:762)
at java.base/java.util.Vector.elementAt(Vector.java:500)
at java.desktop/javax.swing.table.DefaultTableColumnModel.getColumn(DefaultTableColumnModel.java:295)
at java.desktop/javax.swing.JTable.getCellRenderer(JTable.java:5689)
at java.desktop/javax.swing.plaf.basic.BasicTableUI.paintCell(BasicTableUI.java:2184)
at java.desktop/javax.swing.plaf.basic.BasicTableUI.paintDraggedArea(BasicTableUI.java:2160)
at java.desktop/javax.swing.plaf.basic.BasicTableUI.paintCells(BasicTableUI.java:2115)
at java.desktop/javax.swing.plaf.basic.BasicTableUI.paint(BasicTableUI.java:1883)
at java.desktop/javax.swing.plaf.ComponentUI.update(ComponentUI.java:161)
at java.desktop/javax.swing.JComponent.paintComponent(JComponent.java:797)
at java.desktop/javax.swing.JComponent.paint(JComponent.java:1074)
at java.desktop/javax.swing.JComponent.paintToOffscreen(JComponent.java:5255)
at java.desktop/javax.swing.RepaintManager$PaintManager.paintDoubleBufferedImpl(RepaintManager.java:1643)
at java.desktop/javax.swing.RepaintManager$PaintManager.paintDoubleBuffered(RepaintManager.java:1618)
at java.desktop/javax.swing.RepaintManager$PaintManager.paint(RepaintManager.java:1556)
at java.desktop/javax.swing.RepaintManager.paint(RepaintManager.java:1323)
at java.desktop/javax.swing.JComponent._paintImmediately(JComponent.java:5203)
at java.desktop/javax.swing.JComponent.paintImmediately(JComponent.java:5013)
at java.desktop/javax.swing.RepaintManager$4.run(RepaintManager.java:865)
at java.desktop/javax.swing.RepaintManager$4.run(RepaintManager.java:848)
at java.base/java.security.AccessController.doPrivileged(Native Method)
at java.base/java.security.ProtectionDomain$JavaSecurityAccessImpl.doIntersectionPrivilege(ProtectionDomain.java:85)
at java.desktop/javax.swing.RepaintManager.paintDirtyRegions(RepaintManager.java:848)
at java.desktop/javax.swing.RepaintManager.paintDirtyRegions(RepaintManager.java:823)
at java.desktop/javax.swing.RepaintManager.prePaintDirtyRegions(RepaintManager.java:772)
at java.desktop/javax.swing.RepaintManager$ProcessingRunnable.run(RepaintManager.java:1890)
at java.desktop/java.awt.event.InvocationEvent.dispatch(InvocationEvent.java:313)
at java.desktop/java.awt.EventQueue.dispatchEventImpl(EventQueue.java:770)
at java.desktop/java.awt.EventQueue$4.run(EventQueue.java:721)
at java.desktop/java.awt.EventQueue$4.run(EventQueue.java:715)
at java.base/java.security.AccessController.doPrivileged(Native Method)
at java.base/java.security.ProtectionDomain$JavaSecurityAccessImpl.doIntersectionPrivilege(ProtectionDomain.java:85)
at java.desktop/java.awt.EventQueue.dispatchEvent(EventQueue.java:740)
at java.desktop/java.awt.EventDispatchThread.pumpOneEventForFilters(EventDispatchThread.java:203)
at java.desktop/java.awt.EventDispatchThread.pumpEventsForFilter(EventDispatchThread.java:124)
at java.desktop/java.awt.EventDispatchThread.pumpEventsForHierarchy(EventDispatchThread.java:113)
at java.desktop/java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:109)
at java.desktop/java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:101)
at java.desktop/java.awt.EventDispatchThread.run(EventDispatchThread.java:90)