注意:我知道这个Iterator#remove()方法.
在下面的代码示例中,我不明白为什么List.removein main方法抛出ConcurrentModificationException,而不是在remove方法中.
public class RemoveListElementDemo {
private static final List<Integer> integerList;
static {
integerList = new ArrayList<Integer>();
integerList.add(1);
integerList.add(2);
integerList.add(3);
}
public static void remove(Integer toRemove) {
for(Integer integer : integerList) {
if(integer.equals(toRemove)) {
integerList.remove(integer);
}
}
}
public static void main(String... args) {
remove(Integer.valueOf(2));
Integer toRemove = Integer.valueOf(3);
for(Integer integer : integerList) {
if(integer.equals(toRemove)) {
integerList.remove(integer);
}
}
}
}
Run Code Online (Sandbox Code Playgroud) 我正在使用JPA持久化对象.Main对象与另一个对象具有一个拥有的One-Many关系.另一个对象存储在HashMap中.什么样的同步可以解决这个问题?它似乎发生在完全随机的时间,并且非常难以预测.这是我得到的例外:
Exception in thread "pool-1-thread-1" java.util.ConcurrentModificationException
at java.util.HashMap$HashIterator.nextEntry(Unknown Source)
at java.util.HashMap$ValueIterator.next(Unknown Source)
at org.hibernate.collection.AbstractPersistentCollection$IteratorProxy.next(AbstractPersistentCollection.java:555)
at org.hibernate.engine.Cascade.cascadeCollectionElements(Cascade.java:296)
at org.hibernate.engine.Cascade.cascadeCollection(Cascade.java:242)
at org.hibernate.engine.Cascade.cascadeAssociation(Cascade.java:219)
at org.hibernate.engine.Cascade.cascadeProperty(Cascade.java:169)
at org.hibernate.engine.Cascade.cascade(Cascade.java:130)
Run Code Online (Sandbox Code Playgroud) @Test
public void testListCur(){
List<String> li=new ArrayList<String>();
for(int i=0;i<10;i++){
li.add("str"+i);
}
for(String st:li){
if(st.equalsIgnoreCase("str3"))
li.remove("str3");
}
System.out.println(li);
}
Run Code Online (Sandbox Code Playgroud)
当我运行此代码时,我将抛出一个ConcurrentModificationException.
看起来当我从列表中删除指定的元素时,列表不知道它的大小是否已被更改.
我想知道这是集合和删除元素的常见问题吗?
我有这段小代码,它给了我并发修改异常.我无法理解为什么我一直得到它,即使我没有看到任何同时进行的修改.
import java.util.*;
public class SomeClass {
public static void main(String[] args) {
List<String> s = new ArrayList<>();
ListIterator<String> it = s.listIterator();
for (String a : args)
s.add(a);
if (it.hasNext())
String item = it.next();
System.out.println(s);
}
}
Run Code Online (Sandbox Code Playgroud) 我知道如果试图通过简单的循环从集合中删除循环,我会得到这个异常:java.util.ConcurrentModificationException.但我正在使用Iterator,它仍然会产生这个异常.知道为什么以及如何解决它?
HashSet<TableRecord> tableRecords = new HashSet<>();
...
for (Iterator<TableRecord> iterator = tableRecords.iterator(); iterator.hasNext(); ) {
TableRecord record = iterator.next();
if (record.getDependency() == null) {
for (Iterator<TableRecord> dependencyIt = tableRecords.iterator(); dependencyIt.hasNext(); ) {
TableRecord dependency = dependencyIt.next(); //Here is the line which throws this exception
if (dependency.getDependency() != null && dependency.getDependency().getId().equals(record.getId())) {
tableRecords.remove(record);
}
}
}
}
Run Code Online (Sandbox Code Playgroud) 我在Android中同步代码的概念中遗漏了一些东西.
脚本
屏幕上总是绘制3个项目.每个图像都存储在ArrayList(lstGraphics)中.为此,我使用SurfaceView.一旦用户点击图像,图像就会被移除市场并且将添加新的市场.
代码示例:
AnimationHideThread
...
@Override
public void run() {
Canvas c;
while (run) {
c = null;
try {
c = panel.getHolder().lockCanvas(null);
synchronized (panel.getHolder()) {
panel.updatePhysics();
panel.manageAnimations();
panel.onDraw(c);
}
} finally {
if (c != null) {
panel.getHolder().unlockCanvasAndPost(c);
}
}
}
}
...
Run Code Online (Sandbox Code Playgroud)
所以你可以先看看updatePhysics().这意味着我计算每个图像移动到的方向.在这里,我还将删除列表中的点击图像.之后,我检查是否需要在manageAnimations()的列表中添加一个新项目,然后最后一步绘制整个事物.
public class Panel extends SurfaceView implements SurfaceHolder.Callback {
....
public void manageAnimations()
{
synchronized (this.getHolder()) {
...
while (lstGraphics.size()<3) {
lstGraphics.add(createRandomGraphic());
}
}
}
}
@Override
public boolean onTouchEvent(MotionEvent event) {
synchronized (getHolder()) { …Run Code Online (Sandbox Code Playgroud) 如果我在使用for-each循环迭代它时修改Collection,它会给出ConcurrentModificationException.有没有解决方法?
我想使用ConcurrentHashMap让一个线程定期从地图中删除一些项目,并使用其他线程同时从地图中放置和获取项目.
我正在使用map.entrySet().removeIf(lambda)删除线程.我想知道我可以对它的行为做出什么假设.我可以看到该removeIf方法使用迭代器来遍历地图中的元素,检查给定的条件,然后在需要时使用它们将其删除iterator.remove().
文档提供了有关ConcurrentHashMap迭代器行为的一些信息:
类似地,Iterators,Spliterators和Enumerations在迭代器/枚举的创建时或之后的某个时刻返回反映哈希表状态的元素.嘿不要抛出ConcurrentModificationException.但是,迭代器设计为一次只能由一个线程使用.
由于整个removeIf调用发生在一个线程中,我可以确定迭代器当时不被多个线程使用.我仍然想知道下面描述的事件是否可行:
'A'->0map.entrySet().removeIf(entry->entry.getValue()==0) .iteratator()内部removeIf呼叫,并获得迭代器反映了收集的当前状态map.put('A', 1) 'A'->0映射(迭代器反映旧状态),因为0==0它是true,它决定从地图中删除A键.'A'->1但删除线程看到旧值,0并且'A' ->1条目被删除,即使它不应该.地图是空的.我可以想象,实施可以通过多种方式防止这种行为.例如:可能迭代器不反映put/remove操作,但总是反映值更新,或者迭代器的remove方法可能会检查整个映射(键和值)是否仍然存在于映射中,然后才调用键上的remove.我找不到任何有关这些事情的信息,我想知道是否有一些东西可以使用例安全.
java multithreading concurrenthashmap java.util.concurrent concurrentmodification
以下Java代码ConcurrentModificationException按预期抛出:
public class Evil
{
public static void main(String[] args) {
Collection<String> c = new ArrayList<String>();
c.add("lalala");
c.add("sososo");
c.add("ahaaha");
removeLalala(c);
System.err.println(c);
}
private static void removeLalala(Collection<String> c)
{
for (Iterator<String> i = c.iterator(); i.hasNext();) {
String s = i.next();
if(s.equals("lalala")) {
c.remove(s);
}
}
}
}
Run Code Online (Sandbox Code Playgroud)
但是下面的示例(仅在内容中有所不同)Collection执行时没有任何异常:
public class Evil {
public static void main(String[] args)
{
Collection<String> c = new ArrayList<String>();
c.add("lalala");
c.add("lalala");
removeLalala(c);
System.err.println(c);
}
private static void removeLalala(Collection<String> c) {
for (Iterator<String> i …Run Code Online (Sandbox Code Playgroud) 我一直在尝试获取列表的子列表,将其反转,然后将反转的列表放回起始位置。例如,假设我们拥有列表[1, 2, 3, 4, 5, 6],然后从索引2反转到索引4将得到[1, 2, 5, 4, 3, 6]。
我为此编写了一些代码,但是ConcurrentModificationException每次都给出一个代码(除非startIndex == endIndex)。下面提供了一个最小的可重现示例:
int startIndex = 2;
int endIndex = 4;
List<Integer> list = new ArrayList<>();
list.add(1);
list.add(2);
list.add(3);
list.add(4);
list.add(5);
list.add(6);
List<Integer> toReverse = list.subList(startIndex, endIndex+1);
Collections.reverse(toReverse);
list.removeAll(toReverse);
list.addAll(startIndex, toReverse);
Run Code Online (Sandbox Code Playgroud)
异常线程“main” java.util.ConcurrentModificationException
在java.util.ArrayList中的$ SubList.checkForComodification(来源不明)
在java.util.ArrayList的$ SubList.size(来源不明)在
java.util.AbstractCollection.toArray(来源不明)在 test.ConcurrentExample.main(ConcurrentExample.java:64)处
java.util.ArrayList.addAll(Unknown Source
)
错误所指的实际行是list.addAll(startIndex, toReverse);。
我不确定是什么问题,因为迭代过程中似乎没有任何变化。如果有人能解释为什么会这样和/或如何解决它,将不胜感激。
java ×9
collections ×3
list ×2
android ×1
animation ×1
arraylist ×1
exception ×1
foreach ×1
iterator ×1
removechild ×1