Her*_*nis 4 java multithreading synchronization
我做了一些修改,我的多线程程序,并开始获得ConcurrentModificationException一个物体的S- HashTable,所以我做的所有访问在此HashTable为synchronised方法,以避免并发访问我的对象,不像我期望它并没有解决问题.以下是使用的设计概述:
首先,我有一个JTable显示usb设备的一些数据,这JTable要求一个通信核心对象实现Observer(通过Observable对象读取和写入数据到我的设备)它想要的数据,它想要的数据取决于显示哪些行,以便在用户滚动de table时更新,此通信核心对象通过synchronized update调用其他synchronized更新方法的方法获取此通知,该方法HashTable保存最后读取的值(使用后此通信类通知我的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;
}
Run Code Online (Sandbox Code Playgroud)
我需要这种方法,因为我有多个窗口要求来自usb设备的值,并且这个通信对象负责它,在添加HashTable最后一个值之前并发没有问题.这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));
}
Run Code Online (Sandbox Code Playgroud)
Tud*_*dor 12
for (Parameter key : m_lastValues.keySet()) // exception this line
{
// removes the currently not used parameters from the HashTable
}
Run Code Online (Sandbox Code Playgroud)
问题出在这里.无论同步如何,您都无法在迭代时更改集合.实际上这是一个单线程问题.
您可以做的是切换到显式迭代器并使用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;
}
}
}
Run Code Online (Sandbox Code Playgroud)