我得到ArrayList
的索引超出範圍例外。在例外情況下,size()和index在打印時似乎很好。以下是相關的代碼。我有一個自定義表模型,點擊一個按鈕時刷新。儘管訪問的索引在邊界內,ArrayList索引超出範圍
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線程調用reloadData
(重新填充數據對象)後調用fireTableDataChanged
。因此,當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 ;
}
我更感興趣瞭解這裏發生了什麼。我有替代解決方案,如,CopyOnWriteArrayList
等
你在多線程環境中工作嗎? –
不是這樣的。只有'buttonClicked'中看到的'new Thread(new Runnable)是我自己直接創建的。沒有長時間運行的線程,我創建了。 – mpathi
@mpathi你雙擊了嗎?它的可能性發生如果你做了一個雙擊 –