Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/multithreading/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java ConcurrentModificationException的此解决方案安全吗?_Java_Multithreading_Concurrentmodification - Fatal编程技术网

Java ConcurrentModificationException的此解决方案安全吗?

Java ConcurrentModificationException的此解决方案安全吗?,java,multithreading,concurrentmodification,Java,Multithreading,Concurrentmodification,我有第二个线程,我使用OSC发送消息。 在添加消息的主线程中,我遇到了ConcurrentModificationException问题 我所做的修复是,我制作了一个新的列表,其中包含要添加的消息。 在第二个线程中,我将这些消息添加到要发送的列表中 目前它运行没有任何问题,但我想知道这是运气吗? 换句话说,是因为ConcurrentModificationException仍然存在,但现在已经很小了,还是我真的解决了这个问题 public void run() { while (r

我有第二个线程,我使用OSC发送消息。 在添加消息的主线程中,我遇到了ConcurrentModificationException问题

我所做的修复是,我制作了一个新的列表,其中包含要添加的消息。 在第二个线程中,我将这些消息添加到要发送的列表中

目前它运行没有任何问题,但我想知道这是运气吗? 换句话说,是因为ConcurrentModificationException仍然存在,但现在已经很小了,还是我真的解决了这个问题

 public void run() {


    while (running) {

        toSend.addAll(newMessages);
        newMessages.clear();

        Iterator<OSCPriorityMessage> itr = toSend.iterator();

        while (itr.hasNext()) {
            OSCPriorityMessage msg = itr.next();
            oscP5.send(msg, netAddress);
            itr.remove();
        }


        try {
            sleep((long)(waitTime));
        }
        catch (Exception e) {

        }

    }

}

您仍然需要在
newMessages
上同步您访问它的任何位置。我们在这里看到的两个地方是:1)添加到它;2)将它复制到
toSend
中,然后清除它。也许还有更多

public void send(OSCPriorityMessage msg) {

    synchronized(newMessages){
       newMessages.add(msg);
    }
}
要明确说明
toSend
是一个临时的局部列表,仅用于发送过程,请将其声明为局部变量

而不是

toSend.addAll(newMessages);
newMessages.clear();
你能行

ArrayList<OSCPriorityMessage> toSend;
synchronized(newMessages){
   toSend = new ArrayList<>(newMessages);
   newMessages.clear();
}


最后,正如@dlev所建议的,看看
java.util.concurrent
包中现有的线程安全队列实现

您将不会再获得异常,因为唯一更新您正在迭代的列表的线程就是正在迭代列表的同一个线程。只要你对“新消息”列表进行同步访问,这个模式就可以了。也就是说,你可以考虑使用<代码>阻塞队列> />代码>,这是实现生产者/消费者模式(即你正在尝试做的事情)的最佳选择。我也可以使用<代码> toSt.AdvALL(NeWeMeStudio)。在同步块中,对吗?是。只需将其保存在同步块中。我喜欢使用构造函数来实现这一点,但是
addAll
可能更容易阅读。
ArrayList<OSCPriorityMessage> toSend;
synchronized(newMessages){
   toSend = new ArrayList<>(newMessages);
   newMessages.clear();
}
for (OSCPriorityMessage msg: toSend){
    oscP5.send(msg, netAddress);
}