Java如何在循环时添加到数组列表
粒子类别:Java如何在循环时添加到数组列表,java,arraylist,concurrentmodification,Java,Arraylist,Concurrentmodification,粒子类别: Exception in thread "Thread-2" java.util.ConcurrentModificationException at java.util.ArrayList$Itr.checkForComodification(Unknown Source) at java.util.ArrayList$Itr.next(Unknown Source) at biz.boulter.state.Menu.render(Menu.java:21
Exception in thread "Thread-2" java.util.ConcurrentModificationException
at java.util.ArrayList$Itr.checkForComodification(Unknown Source)
at java.util.ArrayList$Itr.next(Unknown Source)
at biz.boulter.state.Menu.render(Menu.java:21)
at biz.boulter.sword.Game.render(Game.java:43)
at biz.boulter.sword.Game.run(Game.java:136)
at java.lang.Thread.run(Unknown Source)
package biz.boulter.swarm;
导入java.awt.Color;
导入java.awt.Graphics2D;
导入java.awt.Rectangle;
公共类粒子{
私人双x=0;
私人双y=0;
私有双xa=0;
私人双ya=0;
私人色彩;
私有矩形img;
公共粒子(int x,int y,int xa,int ya,彩色){
这个.x=x;
这个。y=y;
这个.xa=xa;
this.ya=ya;
this.particlecolor=颜色;
img=新矩形(x,y,5,5);
}
公共无效渲染(图形2D g){
img.setBounds((int)Math.round(x),(int)Math.round(y),5,5);
g、 setColor(particlecolor);
g、 填充(img);
}
公共空白勾号(){
ya+=0.5;
if(xa<0){
xa+=1;
}
如果(xa>0){
xa-=1;
}
x+=xa;
y+=ya;
}
}
为了避免在集合的迭代中出现并发问题和ConcurrentModificationException
,您必须使用并发集合类
例如,对于ArrayList
,您可以尝试使用CopyOnWriteArrayList
,这是ArrayList
的线程安全变体
有关这方面的更多详细信息,请阅读此处:为了避免在集合的迭代中出现并发问题和
ConcurentModificationException
,您必须使用并发集合类
例如,对于ArrayList
,您可以尝试使用CopyOnWriteArrayList
,这是ArrayList
的线程安全变体
更多详细信息请阅读此处:您有两个选项。如果可以,请将方法
勾选
,渲染
和鼠标按下
标记为已同步
。这将解决问题,但如果插入速度更快,这可能不是最好的解决方案
另一个解决办法是改变
package biz.boulter.sword;
import java.awt.Color;
import java.awt.Graphics2D;
import java.awt.Rectangle;
public class Particle {
private double x = 0;
private double y = 0;
private double xa = 0;
private double ya = 0;
private Color particleColour;
private Rectangle img;
public Particle(int x, int y, int xa, int ya, Color colour){
this.x = x;
this.y = y;
this.xa = xa;
this.ya = ya;
this.particleColour = colour;
img = new Rectangle(x, y, 5, 5);
}
public void render(Graphics2D g){
img.setBounds((int)Math.round(x), (int)Math.round(y), 5, 5);
g.setColor(particleColour);
g.fill(img);
}
public void tick(){
ya+=0.5;
if(xa < 0){
xa+=1;
}
if(xa > 0){
xa-=1;
}
x+=xa;
y+=ya;
}
}
private ArrayList particles=new ArrayList();
到
private LinkedBlockingQueue particles=new LinkedBlockingQueue();
这是因为,根据迭代器的方法:
返回的迭代器是一个“弱一致”迭代器,它将
永远不要抛出ConcurrentModificationException,并保证
遍历迭代器构造时存在的元素,
并且可能(但不保证)反映任何修改
施工之后
你有两个选择。如果可以,请将方法
勾选
,渲染
和鼠标按下
标记为已同步
。这将解决问题,但如果插入速度更快,这可能不是最好的解决方案
另一个解决办法是改变
package biz.boulter.sword;
import java.awt.Color;
import java.awt.Graphics2D;
import java.awt.Rectangle;
public class Particle {
private double x = 0;
private double y = 0;
private double xa = 0;
private double ya = 0;
private Color particleColour;
private Rectangle img;
public Particle(int x, int y, int xa, int ya, Color colour){
this.x = x;
this.y = y;
this.xa = xa;
this.ya = ya;
this.particleColour = colour;
img = new Rectangle(x, y, 5, 5);
}
public void render(Graphics2D g){
img.setBounds((int)Math.round(x), (int)Math.round(y), 5, 5);
g.setColor(particleColour);
g.fill(img);
}
public void tick(){
ya+=0.5;
if(xa < 0){
xa+=1;
}
if(xa > 0){
xa-=1;
}
x+=xa;
y+=ya;
}
}
private ArrayList particles=new ArrayList();
到
private LinkedBlockingQueue particles=new LinkedBlockingQueue();
这是因为,根据迭代器的方法:
返回的迭代器是一个“弱一致”迭代器,它将
永远不要抛出ConcurrentModificationException,并保证
遍历迭代器构造时存在的元素,
并且可能(但不保证)反映任何修改
施工之后
最简单的方法是在使用集合时锁定集合
private LinkedBlockingQueue<Particle> particles = new LinkedBlockingQueue<Particle>();
及
这样可以确保访问不是并发的
CopyOnWriteArrayList的问题在于写入成本很高。顾名思义,它在每次更新时都会复制整个列表
BlockingQueue的问题在于它不是为迭代而设计的。它可以工作,但效率不高。最简单的方法是在使用集合时锁定集合
private LinkedBlockingQueue<Particle> particles = new LinkedBlockingQueue<Particle>();
及
这样可以确保访问不是并发的
CopyOnWriteArrayList的问题在于写入成本很高。顾名思义,它在每次更新时都会复制整个列表
BlockingQueue的问题在于它不是为迭代而设计的。它可以工作,但效率不高。您试图更改数组的内部状态,而在循环时,这是预期的行为 一个快捷的方法(但会带来一些性能成本)是使用CopyOnWriteArrayList,请参阅链接条目,
您试图更改数组的内部状态,而循环时,这是预期的行为 一个快捷的方法(但会带来一些性能成本)是使用CopyOnWriteArrayList,请参阅链接条目,
在哪里捕获
ConcurrentModificationException
,显示stacktrace。如果在执行tick()或render()时捕获mousePressed事件,则在执行列表时将进行添加尝试,这是非法的。您需要实现一些并发安全机制。查找同步的信号量…好的,我添加了堆栈跟踪显示方法Particle.tick()和Particle.render()的代码。我认为问题就在这里。在哪里捕获ConcurrentModificationException,显示stacktrace。如果在执行tick()或render()时捕获mousePressed事件,则在执行列表时将进行添加尝试,这是非法的。您需要实现一些并发安全机制。查找同步的信号量…好的,我添加了堆栈跟踪显示方法Particle.tick()和Particle.render()的代码。我认为问题就在那里。
synchronized(particles) {
for(Particle p: particles){
p.tick();
}
}
Particle p = new Particle(x, y, rand, Game.rand.nextInt(10)-11, new Color(Game.rand.nextInt(1000000000)))
synchronized(particles) {
particles.add(p);
}