我对我的多线程程序进行了一些修改,并开始在对象的ConcurrentModificationException
上获取HashTable
,因此我将对HashTable
的所有访问权限转换为synchronised
方法避免并发访问我的对象,不像我期望的那样它没有解决问题。以下是所用设计的概述:
首先我有一个JTable
显示一些usb设备的数据,这个JTable
要求一个实现Observer
的通信核心对象(读写的那个)数据到我的设备)通过Observable
对象得到它想要的数据,它想要的数据取决于显示哪些行,以便在用户滚动de table时更新,而不是通信核心对象通过{{获取此通知1}}调用其他synchronized update
方法的方法,该方法更新synchronized
,保存后使用的最后读取值(此通信类在读取值时通知我的HashTable
类和其他对象虽然其他JTable
对象)。在更新Observable
时,最后一种方法出现异常。这是代码的简化:
以下方法属于通信核心对象
HashTable
我需要这种方法,因为我有多个窗口要求来自usb设备的值,并且这个通信对象负责处理,在我添加最后一个值的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
m_lastValues
未在上面未列出的任何其他方法中使用。
有什么建议吗?提前谢谢。
[编辑]
实际上这不是一个多线程问题,它只是一个被误解的异常含义。正如@Tudor所指出的那样,问题是HashTable
循环中的remove()
方法。以下是我解决它的方法:
此代码进入while
方法,请注意updateMonitorList()
(第一个问题是no Iterator was needed
循环),实际上for
没有区别:< / p>
Iterator
答案 0 :(得分:12)
for (Parameter key : m_lastValues.keySet()) // exception this line
{
// removes the currently not used parameters from the HashTable
}
问题出在这里。无论同步如何,您都无法在迭代时更改集合。实际上这是一个单线程问题。
您可以做的是切换到explicit iterator并使用remove()
或保存要在单独的集合中删除的项目,然后将其删除。
Iterator<Parameter> iter = m_lastValues.keySet().iterator();
while (iter.hasNext()) {
Parameter current = iter.next();
for (int i = 0; i < m_monitorList.size(); i++) {
if(current.equals(m_monitorList.get(i)) {
iter.remove();
break;
}
}
}