与Java的并发性';s LinkedList类
你好 我与Java中的LinkedList存在并发问题。我有一个名为“Connection”的对象类型,它的成员变量是名为“listeners”的“MessageHandlers”的LinkedList。然后我有两个不同的线程,一个在修改,另一个在同一个LinkedList上迭代 我见过许多其他的StackOverflow问题,建议使用同步化的代码块,但这似乎并没有帮助所有人。我还尝试将LinkedList创建为一个并发的链接列表,但我仍然收到与Java的并发性';s LinkedList类,java,multithreading,concurrency,thread-safety,Java,Multithreading,Concurrency,Thread Safety,你好 我与Java中的LinkedList存在并发问题。我有一个名为“Connection”的对象类型,它的成员变量是名为“listeners”的“MessageHandlers”的LinkedList。然后我有两个不同的线程,一个在修改,另一个在同一个LinkedList上迭代 我见过许多其他的StackOverflow问题,建议使用同步化的代码块,但这似乎并没有帮助所有人。我还尝试将LinkedList创建为一个并发的链接列表,但我仍然收到 Exception in thread "Thr
Exception in thread "Thread-1" java.util.ConcurrentModificationException
例外。有人有其他建议可以尝试吗?下面是我的一些代码片段
public synchronized Object ReadObject() throws java.io.IOException
{
Object obj = null;
try
{
obj = input.readObject();
synchronized(listeners)
{
Iterator<MessageHandler> i = listeners.iterator();
while(i.hasNext())
{
i.next().MessageReceived(obj, this);
}
}
}
catch (IOException e)
{
e.printStackTrace();
throw e;
}
catch (ClassNotFoundException e)
{
// TODO Auto-generated catch block
e.printStackTrace();
}
return obj;
}
然后调用方法user.getConnection().getListeners().add(this),从而得到异常
public Connection()
{
//Initialize the variables to NULL
socket = null;
output = null;
input = null;
receiveThread = null;
runReceiveThread = false;
listeners = Collections.synchronizedList(new LinkedList<MessageHandler>());
//Handle the ID counter. Now we have a unique ID for every connection that comes in
connectionID = counterID;
counterID = counterID + 1;
}
公共连接()
{
//将变量初始化为NULL
socket=null;
输出=空;
输入=空;
receiveThread=null;
runReceiveThread=false;
listeners=Collections.synchronizedList(新的LinkedList());
//处理ID计数器。现在,每个连接都有一个唯一的ID
connectionID=计数器ID;
计数器ID=计数器ID+1;
}
这是连接类的构造函数。注意他收藏。同步列表
有什么想法吗?非常感谢你的帮助 同步的
块看起来应该可以工作。我希望在修改列表的ReadObject
synchronized
块中调用的方法中会有活动。您的MessageHandler
s是否调用或链接到对addNewLoggedInUser
的调用(或任何其他可能更新侦听器列表的方法)
如果是这样的话,线程将已经让监视器被ReadObject
同步块抓取,并且能够在addNewLoggedInUser
java.util.ConcurrentModificationException
中输入该块。这是由于修改了由迭代器锁定的列表造成的。我想您是从MessageReceived()
调用addNewLoggedInUser()
。这将导致并发修改异常,因为调用函数在linkedlist上已经有迭代器锁。通过BlockingQueue javadoc。它还提到了一个适合您需求的简单场景,即
class Producer implements Runnable {
private final BlockingQueue queue;
Producer(BlockingQueue q) { queue = q; }
public void run() {
try {
while (true) { queue.put(produce()); }
} catch (InterruptedException ex) { ... handle ...}
}
Object produce() { ... }
}
class Consumer implements Runnable {
private final BlockingQueue queue;
Consumer(BlockingQueue q) { queue = q; }
public void run() {
try {
while (true) { consume(queue.take()); }
} catch (InterruptedException ex) { ... handle ...}
}
void consume(Object x) { ... }
}
class Setup {
void main() {
BlockingQueue q = new SomeQueueImplementation();
Producer p = new Producer(q);
Consumer c1 = new Consumer(q);
Consumer c2 = new Consumer(q);
new Thread(p).start();
new Thread(c1).start();
new Thread(c2).start();
}
}
同步块参数中的user.getConnection().getListeners()和listeners是否为同一实例?在对列表进行迭代时更改列表(添加/删除元素)时引发。您可以使用单个线程导致此异常。除非有多个线程同时访问列表,否则不需要任何类型的并发集合。例如。@George谢谢!我很长时间都不明白你的意思,因为我认为我没有很好地解释代码,因为我认为你的回答太离谱了。事实证明,你是完全正确的!我没有看到我在做什么,直到我在一个较小的示例上再次这样做,并看到相同的异常被抛出。谢谢你的帮助,乔治!是的,我的一个MessageHandler调用addNewLoggedInUser。我不熟悉“监视器”是什么,所以我必须对此做一些研究。谢谢你的提示。
class Producer implements Runnable {
private final BlockingQueue queue;
Producer(BlockingQueue q) { queue = q; }
public void run() {
try {
while (true) { queue.put(produce()); }
} catch (InterruptedException ex) { ... handle ...}
}
Object produce() { ... }
}
class Consumer implements Runnable {
private final BlockingQueue queue;
Consumer(BlockingQueue q) { queue = q; }
public void run() {
try {
while (true) { consume(queue.take()); }
} catch (InterruptedException ex) { ... handle ...}
}
void consume(Object x) { ... }
}
class Setup {
void main() {
BlockingQueue q = new SomeQueueImplementation();
Producer p = new Producer(q);
Consumer c1 = new Consumer(q);
Consumer c2 = new Consumer(q);
new Thread(p).start();
new Thread(c1).start();
new Thread(c2).start();
}
}