【发布时间】:2016-05-07 13:07:19
【问题描述】:
我收到ArrayList 的索引越界异常。在异常点, size() 和 index 在打印时似乎很好。下面是相关代码。我有一个自定义表模型,单击按钮时会刷新。
public class CallingClass
{
public void buttonClicked()
{
new Thread(new Runnable()
{
public void run()
{
dataTableModel.refresh();
}
}).start();
}
}
public class DataTableModel extends AbstractTableModel
{
protected ArrayList<Object> data;
public DataTableModel()
{
data = new ArrayList<Object>();
}
public Object getValueAt(int modelRow, int modelColumn)
{
// Throws Index Out of Bounds Exception though a println here shows modelRow value within 0 to data.size()-1
// DataObject is just an interface to support getValue method
return ((DataObject) data.get(modelRow)).getValue();
}
public void refresh()
{
reloadData();
fireTableDataChanged();
}
protected void reloadData()
{
ArrayList<TextMessage> messageList = jmsConnection.getMessageList();
data.clear();
try
{
for(int i=0; i<messageList.size(); ++i)
{
data.add(new MyDataObject(messageList.get(i).getJMSMessageID()));
}
}
catch(Exception e)
{
}
}
}
如您所见,DataTableModel.refresh() 在新线程中运行。对fireTableDataChanged 的调用可能会导致eventQueue 线程重新绘制表格,进而调用getValueAt 方法。尽管modelRow 的值小于data.size(),但这里还是会抛出异常。不确定如何存在竞争条件,因为 Runnable 线程在调用 fireTableDataChanged 之后调用 reloadData(它重新填充数据对象)。因此,当 eventQueue 线程调用 getValueAt 时,data 对象应该是稳定的。另请注意,在可运行线程出现之前,刷新按钮处于禁用状态,以避免重复调用刷新。
下面是异常信息
Exception in thread "AWT-EventQueue-0" java.lang.IndexOutOfBoundsException: Index: 3, Size: 10
at java.util.ArrayList.rangeCheck(Unknown Source)
at java.util.ArrayList.get(Unknown Source)
at datatablemodels.DataTableModel.getValueAt(DataTableModel.java:70)
如果我稍微更改 reloadData 代码,异常就会消失(至少还不能重现)。我的猜测是,它只是减少了异常的可能性。
protected void reloadData()
{
ArrayList<TextMessage> messageList = jmsConnection.getMessageList();
ArrayList<Object> tempdata = new ArrayList<Object>();
try
{
for(int i=0; i<messageList.size(); ++i)
{
tempdata.add(new MyDataObject(messageList.get(i).getJMSMessageID()));
}
}
catch(Exception e)
{
}
data = tempdata ;
}
我更感兴趣的是了解这里发生了什么。我确实有其他解决方案,例如 synchronized、CopyOnWriteArrayList 等。
【问题讨论】:
-
您是否在多线程环境中工作?
-
并非如此。只有您在
buttonClicked中看到的new Thread(new Runnable是我直接创建的。我没有创建长时间运行的线程。 -
@mpathi 你双击了吗?如果您双击,它可能会发生。
-
不双击。我也对此表示怀疑。因此,我在每次点击之间用 4 到 5 秒的单次点击进行了缓慢的测试。该问题随机发生。有时在点击 3 次后,有时在点击 30 次后。
-
您确实需要将其缩减为最低完整可验证示例stackoverflow.com/help/mcve
标签: java multithreading exception arraylist