我对我的多线程程序进行了一些修改,并开始ConcurrentModificationException
在对象的 s 处获取 s HashTable
,因此我将对它的所有访问都设置HashTable
为synchronised
方法以避免对我的对象的并发访问,与我的预期不同,它没有解决问题。以下是使用的设计大纲:
首先,我有一个JTable
显示 USB 设备的一些数据的对象,这JTable
需要一个通信核心对象,该对象通过对象实现Observer
(读取和写入数据到我的设备的Observable
对象)它想要的数据,它想要的数据取决于显示哪些行,以便在用户滚动表格时更新它,而不是此通信核心对象通过synchronized update
调用其他synchronized
方法的方法获取此通知,该方法更新 aHashTable
保存最后读取的值以供使用后使用(此通信类通知我的JTable
类和其他对象,当它通过其他Observable
对象读取值时)。在更新HashTable
. 这是代码的简化:
以下方法是通信核心对象
public synchronized void update(Observable o, Object arg)
{
// do some other work
// calls the second synchronized method
updateMonitorList();
}
private synchronized void updateMonitorList()
{
// updates a list of monitoring addresses (no problem here)
// m_lastValues is the HashTable that is giving me headaches
Iterator<Parameter> itr = m_lastValues.keySet().iterator();
while (itr.hasNext())
{
// removes the currently not used parameters from the HashTable
Parameter p = itr.next(); // concurrent exception here WHY? :/
boolean contains = false;
for (int i = 0; i < m_monitorList.size(); i++)
{
if (p.equals(m_monitorList.get(i)))
{
contains = true;
break;
}
}
if (!contains)
{
m_lastValues.remove(p);
}
}
// more operations with the HashTable
for (int i = 0; i < m_monitorList.size(); i++)
{
// adds newly added parameters to the hashtable
boolean contains = false;
for (Observer key : m_requestedParameters.keySet())
{
if (key.equals(m_monitorList.get(i)))
{
contains = true;
break;
}
}
if (!contains)
{
m_lastValues.put(m_monitorList.getAt(i), m_monitorList.getAt(i).m_intUserSetting);
}
}
}
// this method is used to know if a value has changed
private synchronized boolean getParameterChanged(Parameter currentParamer)
{
Integer v = m_lastValues.get(currentParamer);
return v == null || v != currentParamer.m_intUserSetting;
}
HashTable
我需要这种方法,因为我有多个窗口从 USB 设备请求值,并且这个通信对象负责处理它,在我添加最后一个值之前并发没有问题。这m_lastValues
HashTable
不用于上面未列出的任何其他方法。
有什么建议么?提前致谢。
[ 编辑 ]
其实那不是多线程问题,只是被误解的异常含义。正如@Tudor 指出的那样,问题在于循环remove()
内的方法。while
这是我解决它的方法:
这段代码进入updateMonitorList()
方法,请注意no Iterator was needed
(第一个问题是for
这样的循环),实际上Iterator
没有区别:
ArrayList<Parameter> remove = new ArrayList<Parameter>();
for (Parameter p : m_lastValues.keySet())
{
boolean contains = false;
for (int i = 0; i < m_monitorList.size(); i++)
{
if (p.equals(m_monitorList.get(i)))
{
contains = true;
break;
}
}
if (!contains)
{
remove.add(p);
}
}
for (int i = 0; i < remove.size(); i++)
{
m_lastValues.remove(remove.get(i));
}