标签: concurrentmodification

陷入"java.util.ConcurrentModificationException"

这是我的代码:

// eventList is a LinkedList

public void run() {

    Iterator<Event> it = eventList.iterator();
    int size = eventList.size();

    while(size > 0) {
        while(it.hasNext()) {
            Event e = it.next(); //flaged line

            if(e.ready()) {
                System.out.println(e);
                e.action();
                eventList.remove(e);
                --size;
            }
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

错误java.util.ConcurrentModificationException是在flag lined(Event e = it.next();)处抛出的.你是否在我的代码中看到一个错误,这个错误明显是抛出异常的原因?

java exception linked-list concurrentmodification

6
推荐指数
1
解决办法
3509
查看次数

如何在并发线程中操作`values()`和`put()`时避免使用HashMap"ConcurrentModificationException"?

码:

我有一个HashMap

private Map<K, V> map = new HashMap<>();
Run Code Online (Sandbox Code Playgroud)

一种方法是通过调用将KV对放入其中put(K,V).

另一种方法想从其值中提取一组随机元素:

int size = map.size();    // size > 0
V[] value_array = map.values().toArray(new V[size]);
Random rand = new Random();
int start = rand.nextInt(size); int end = rand.nextInt(size);
// return value_array[start .. end - 1]
Run Code Online (Sandbox Code Playgroud)

这两个方法在两个不同的并发线程中调用.


错误:

我收到一个ConcurrentModificationException错误:

at java.util.HashMap$HashIterator.nextEntry(Unknown Source)
at java.util.HashMap$ValueIterator.next(Unknown Source)
at java.util.AbstractCollection.toArray(Unknown Source)
Run Code Online (Sandbox Code Playgroud)

似乎toArray()一个线程中的方法实际上是在HashMap上迭代,并且put()在其他线程中发生了修改.

问题:如何在并发线程中使用HashMap.values().toArray()和HashMap.put()时避免"ConcurrentModificationException"?
直接避免values().toArray()在第二种方法中使用也行.

java concurrency multithreading hashmap concurrentmodification

6
推荐指数
1
解决办法
2万
查看次数

执行任何类型的迭代时,Java 8 ConcurrentModificationException

试图找出这个问题2周,但没有任何成功.:X

它发生在我进行任何类型的迭代时,但主要是在使用#forEach时.

我不是以任何方式修改列表,也不是它的元素,所以这对我来说似乎很尴尬.示例代码:

    Map<Season, List<Team>> map = fetcher.getTeamsIn(ids);

    Set<Team> toCreateTeams = new HashSet<>();
    Set<Team> toUpdateTeams = new HashSet<>();

    map.forEach((k, v) -> {
        toCreateTeams.addAll(v.stream().filter(t -> !persistedTeams.containsKey(t.getId())).collect(Collectors.toSet()));
        toUpdateTeams.addAll(v.stream().filter(t -> {
            Date latestPersistedUpdate = persistedTeams.get(t.getId());
            return latestPersistedUpdate != null && t.getLastUpdated().after(latestPersistedUpdate);
        }).collect(Collectors.toSet()));
    });
Run Code Online (Sandbox Code Playgroud)

map在#getTeamsIn中实例化 new HashMap<>();

试图打破eclipse中的异常,看看是否有些线程正在做一些疯狂的事情,但一切看起来都很正常.在下面的图片中,异常是在迭代时抛出map.

ConcurrentModificationException线程堆栈跟踪 ConcurrentModificationException线程堆栈跟踪

我也开始有其他非常奇怪的行为,比如永远陷入lambda表达式.在这种情况下,在我看来Eclipse正在表达式中停止(出于某种未知的原因),就好像在行中设置了一些断点一样.当我暂停执行并恢复有问题的线程时,流程才会恢复正常(直到下一个lambda表达式)或一些疯狂的ConcurrentModificationException.

因未知原因停止表达

整个事情对我来说似乎是一些Eclipse疯狂的错误,但我真的不想重建我的环境,如果是这样的话.

我正在使用

Java(TM) SE Runtime Environment (build 1.8.0_45-b14)
Java HotSpot(TM) 64-Bit Server VM (build 25.45-b02, mixed mode)
Run Code Online (Sandbox Code Playgroud)

在Linux Mint上.

谢谢!

- 更新1 -

需要明确的是:即使对于这个简单的例子,错误也在发生:

map.forEach((k, v) -> {
    System.out.println("Test" + k.getId());
});
Run Code Online (Sandbox Code Playgroud)

一些可能很重要的随机信息:例外仅在打印完地图的最后一个元素后才会爆炸! …

java foreach lambda concurrentmodification

6
推荐指数
1
解决办法
2163
查看次数

java HashMap的快速行为失败

我一起玩java.util.HashMap,了解fail-fast行为是什么.

HashMap map = new HashMap();
map.put("jon", 10);
map.put("sean", 11);
map.put("jim", 12);
map.put("stark", 13);
map.put("vic", 14);
Set keys = map.keySet();
for(Object k:keys) {
    System.out.println(map.get(k));
}

for(Object k:keys) {
   String key =(String)k;
   if(key.equals("stark")) {
      map.remove(key);
    }
}

System.out.println("after modifn");
for(Object k:keys) {
    System.out.println(map.get(k));
}
Run Code Online (Sandbox Code Playgroud)

我得到了结果

12
11
10
14
13
after modifn
12
11
10
14
Run Code Online (Sandbox Code Playgroud)

我也尝试过使用迭代器

Iterator<String> itr = keys.iterator();
while(itr.hasNext()) {
    String key = itr.next();
    if(key.equals("stark")) {
        map.remove(key);
    }
}
Run Code Online (Sandbox Code Playgroud)

ConcurrentModificationException在任何一种情况下我都没有得到任何东西..这是因为(来自javadoc)

迭代器的快速失败行为无法得到保证,因为一般来说,在存在非同步并发修改的情况下,不可能做出任何硬性保证.失败快速迭代器会尽最大努力抛出ConcurrentModificationException

我查了另一个帖子 …

java hashmap concurrentmodification

5
推荐指数
1
解决办法
968
查看次数

如何在Java中的链接列表中使用两个不同的迭代器?

我想使用链表来执行元素的提取和插入,尝试启发式的所有组合.链接列表对于此类操作更有效.因为我想尝试所有可能的提取/插入对,我在列表中使用了两个不同的迭代器.这引发了"ConcurrentModificationException".如何在不重新遍历列表的情况下有效地执行此操作,因为这会破坏首先使用列表的整个目的?

以下是代码的相关部分:

ListIterator<Integer> it1 = data.listIterator();
ListIterator<Integer> it2;

while(it1.hasNext()) {
    int i = it1.next();
    it2 = data.listIterator();

    while(it2.hasNext()) {
        if (i == it2.next()) continue; // continue right away when the indexes are equal
        it1.remove();
        it2.add(i);
        if (length() < best)
            return true;
        }

    // when the swap is not better/consistent
    it2.remove();
    it1.add(i);
}
return false;
Run Code Online (Sandbox Code Playgroud)

谢谢

java iterator heuristics linked-list concurrentmodification

5
推荐指数
1
解决办法
2089
查看次数

Java观察者模式 - 如何在更新(通知)循环/迭代期间删除观察者?

我对java很新,所以如果我说的话听起来很新鲜,那就要提前对不起.

我已经实现了一个基本的观察者模式.一些观察者应该只听一个更新,然后立即从观察者/听众列表中删除自己.但是,每当我尝试这样做时,我都会遇到着名的java.util.concurrentmodificationexception错误.

我显然遇到了这个错误,因为我在更改列表的同时还在迭代它,但我仍然不确定什么是正确的解决方案.我想知道我是否以正确的方式做到这一点.如果我是,那么它需要什么样的解决方案才能使它工作?如果我不是,我想得到更好的方法来实现我想要做的建议.

这是我的代码:

public interface Listener {
    public void onValueChange(double newValue);
}   


public class Observed {
    private int value;
    List<Listener>  listeners  = new ArrayList<>();

    public void addListener(Listener toAdd) {
        listeners.add(toAdd);
    }

    public void removeListener(Listener toRemove) {
        listeners.remove(toRemove);
    }

    public void changeValue(double newValue) {
        value = newValue;
        for (Listener l : listeners) l.onValueChange(newValue);                               
    }
}


public class SomeClassA implements Listener{
    private Observed observed;

    SomeClassA(Observed observed) {
        this.observed = observed;
    }

    @Override
    public void onValueChange(double newValue) {
        System.out.println(newValue);
        observed.removeListener(this); …
Run Code Online (Sandbox Code Playgroud)

java concurrentmodification observer-pattern

5
推荐指数
1
解决办法
4100
查看次数

多个线程访问一个变量

我在正在阅读的教科书中发现了这个问题.解决方案也在下面给出.我无法理解最小值是多少2.为什么线程不能读取0,所有其他线程都执行并写入1?无论是1还是2,最后写的线程还必须完成自己的循环?

int n = 0;
int main(int argc, char **argv) {
 for (i = 0; i < 5; i++) {
 int tmp = n;
 tmp = tmp + 1;
 n = tmp;
 }
 return 0;
}
Run Code Online (Sandbox Code Playgroud)

如果单个线程运行此应用程序,您可能希望最终输出为5.如果5个线程并行运行相同的循环,该怎么办?n可能具有的最大和最小值是多少?最大的应该是selfevident:25,从5个线程增加5个.然而,关于最小可能值的推理更加困难.提示:n可以小于5,但是由你决定原因.

解:

由于五个线程运行此五次迭代循环并且没有并发访问的保护,因此n可以达到的最低值是两个.从最终结果向后工作时,了解如何达到此结果是最简单的.对于最终输出为2,线程必须从n读取值1,递增它,然后写入2.这意味着另一个线程写了一个,暗示它最初也读为零(这也是n的起始值).这解释了五个线程中的两个线程的行为.但是,要发生此行为,必须覆盖其他三个线程的结果.两个有效的执行可以实现这一点.要么1)所有三个线程开始并在第一个线程读取零和写入一个之间完成执行,或者2)所有三个线程开始并在最终线程读取一个和写入两个之间完成执行.两个执行顺序都有效.

c multithreading concurrentmodification

5
推荐指数
1
解决办法
1752
查看次数

私有变量线程安全吗

当两个线程尝试修改对象的数据时,正在开发 api(如 Java 中的 Collections api)的开发人员是否应该手动抛出 ConcurrentModificationException?

为什么这段代码不会在多个线程尝试修改Person's 对象的内容时抛出异常?

public class Main {

    public static void main(String[] args) {
    // write your code here
        RunnableDemo r = new RunnableDemo();
        for (int i = 0; i < 10; i++) {
            Thread t = new Thread(r, "Thread " + i);
            t.start();
        }
    }
}

class RunnableDemo implements Runnable {

    private Person person = new Person();

    @Override
    public void run() {
        for (int i = 0; i < 100; i++) { …
Run Code Online (Sandbox Code Playgroud)

java multithreading thread-safety concurrentmodification

5
推荐指数
1
解决办法
1662
查看次数

为什么对foreach方法进行并发修改而不对for循环进行修改

 ArrayList<Integer> targets = new ArrayList<Integer>();
 targets.add(2);
 targets.add(2);

 for (Integer testInt : targets )
 {
       targets.add(1);
 }
Run Code Online (Sandbox Code Playgroud)

我得到一个concurrentModificationException,但正常的for循环.我没有任何例外.在正常的forloop像: -

for(int i=0;i<target.size();i++)
{
   System.out.println(target.get(i));
   target.add(22); //no exception
   target.remove(2) // no exception 
}
Run Code Online (Sandbox Code Playgroud)

java concurrentmodification

5
推荐指数
1
解决办法
404
查看次数

修改 SnapshotStateList 会引发 ConcurrentModificationException

的文档SnapshotStateList指出它类似于常规的可变列表。我有一个用例,我需要修改列表 ( ) 中的所有元素set case。这不会改变列表的大小,但我遇到了 ConcurrentModificationException。

我在这里创建了一个非常简化的用例版本。以下 kotlin 列表运行良好:

val myList2 = mutableListOf("a", "b", "c")
myList2.forEachIndexed { index, _ ->
    // Modify item at index
    myList2[index] = "x"
}
Run Code Online (Sandbox Code Playgroud)

但我在这里遇到并发修改异常:

val myList = mutableStateListOf("a", "b", "c")
myList.forEachIndexed { index, _ ->
    // Modify item at index but I get an exception
    myList[index] = "x"
}
Run Code Online (Sandbox Code Playgroud)

如何修改mutableStateList()in place 的所有元素而不出现并发修改异常?

编辑:

我可以创建一个副本mutableStateList来迭代它,它工作得很好,但由于我没有更改列表的大小,是否可以就地执行它?

android concurrentmodification kotlin

5
推荐指数
1
解决办法
1247
查看次数