Java中的变量值消失

Java中的变量值消失,java,variables,physics,Java,Variables,Physics,我正在用Java做一个基本的粒子模拟器。现在,我所做的就是让粒子以等效于电力的方式相互作用。这一部分工作得很好(或者至少和您期望的基本模型一样好) 但是,当我添加一些粒子时,程序会丢失它们的位置、速度和加速度值,但不会丢失其他数据(例如,它们的ID号)。对于相同数量的粒子,这并不总是发生。有时,当我添加第四、第五、第二或第三个粒子时,会发生这种情况,但不会添加第一个粒子。它总是发生在我单击添加粒子时,当它失败后,我无法再添加任何东西(这很奇怪),并且粒子不再移动(正如您所期望的,它们的速度和加速

我正在用Java做一个基本的粒子模拟器。现在,我所做的就是让粒子以等效于电力的方式相互作用。这一部分工作得很好(或者至少和您期望的基本模型一样好)

但是,当我添加一些粒子时,程序会丢失它们的位置、速度和加速度值,但不会丢失其他数据(例如,它们的ID号)。对于相同数量的粒子,这并不总是发生。有时,当我添加第四、第五、第二或第三个粒子时,会发生这种情况,但不会添加第一个粒子。它总是发生在我单击添加粒子时,当它失败后,我无法再添加任何东西(这很奇怪),并且粒子不再移动(正如您所期望的,它们的速度和加速度为0)

我将粒子存储在ArrayList中。数组不会丢失数据(我已经检查过了,对象在其中,我甚至可以调用它们的toString()方法并检索它们的ID)。这个问题似乎与同步有关(考虑到它并不总是在同一时刻发生,它似乎有点随机),但我不知道它是什么

我在下面留下所有相关代码

    public class Scene implements KeyListener, MouseListener, MouseMotionListener{

    public static ArrayList<Particle> particleArray = new ArrayList<Particle>();

    public static Object particleLock = new Object();

    public void update() {

        synchronized(particleLock) {
            for(Particle particle: particleArray) {
                double resultX = 0;
                double resultY = 0;

                for(int i = 0; i<particleArray.size(); i++) {
                    if(i != particleArray.indexOf(particle)) {
                        double[] result = PhysicsEngine.applyElectircalForce(particle, particleArray.get(i));
                        resultX += result[0];
                        resultY += result[1];
                    }
                }

                particle.netForceX = resultX;
                particle.netForceY = resultY;

                particle.update();
            }
        }
    }

public void mousePressed(MouseEvent e) {
        int mouseX = e.getX();
        int mouseY = e.getY();
        boolean positive = true;

        if(e.getButton() == MouseEvent.BUTTON1) {
            positive = true;
        } else if(e.getButton() == MouseEvent.BUTTON3) {
            positive = false;
        }


        synchronized(particleLock){
            particleArray.add(new Particle(mouseX, mouseY, positive));
            System.out.println("New particle added at " + mouseX + ", " + mouseY);
        }
    }
}

public class Particle{

public double x;
    public double y;

    public Point2D position;

    public double velX;
    public double velY;

    public double acX;
    public double acY;

    private Color particleColor;
    private int radius = 10;


    // PHYSICS
    public double mass;
    public double charge;
    public double netForceX;
    public double netForceY;

    private boolean positive;

public Particle(double x, double y, boolean positive) {
        this.x = x - radius;
        this.y = y - radius;

        this.velX = 3;
        this.velY = 2;

        this.acX = 0;
        this.acY = 0;

        this.mass = 100;
        this.positive = positive;

        if(positive) {
            this.charge = defaultCharge;
        } else {
            this.charge = defaultCharge*(-1);
        }

        this.position = new Point2D.Double(x, y);

        particleColor = Color.WHITE;
}

public void update() {

        acX = netForceX / mass;
        acY = netForceY / mass;

        velX += acX;
        velY += acY;

        if(x<=0 || x>=Simulation.WIDTH - 23){
            velX = velX * -1;
            x+= velX;
        }

        if(y<=0 || y>=Simulation.HEIGHT - 35){
            velY = velY * -1;
            y+= velY;
        }

        synchronized(Scene.particleLock) {
            for(Particle otherPart: Scene.particleArray) {

                if(otherPart.equals(this)) {
                    continue;
                }

                double distance = otherPart.position.distance(position);


                if(distance <= radius + otherPart.radius) {
                    //aplicar lo que sé de choques de alguna manera
                }
            }
        }

        x+= velX;
        y+= velY;

        position.setLocation(x, y);
    }
}

public class PhysicsEngine {

    static double electricalConstant = 100000;

    public static double[] applyElectircalForce(Particle thisPart, Particle otherPart) {

        double distance = otherPart.position.distance(thisPart.position);

        double angle = Math.asin(Math.abs(thisPart.y - otherPart.y)/distance);

        double force = (electricalConstant * thisPart.charge * otherPart.charge)/Math.pow(distance, 2);

        double forceX = force * Math.cos(angle);
        double forceY = force * Math.sin(angle);

        if(otherPart.x < thisPart.x) {
            forceX = forceX*(-1);
        }

        if(otherPart.y < thisPart.y) {
            forceY = forceY*(-1);
        }

        double[] result = {forceX, forceY};

        return result;
    }
}
公共类场景实现KeyListener、MouseListener、MouseMotionListener{
public static ArrayList particleArray=new ArrayList();
公共静态对象particleLock=新对象();
公共无效更新(){
已同步(particleLock){
用于(粒子:粒子光线){
双结果=0;
双结果=0;

对于(int i=0;i我曾经在处理android项目时遇到过类似的同步问题,请尝试声明particleArray volatile,以便编译器知道particleArray将在其他线程或多个线程上更改。如果不起作用,我建议使用队列从不同线程推送对粒子数组的更改然后在update方法中拖动对数组列表的预期更改以更新粒子数组列表。根据我的经验,在不同线程之间直接更改值几乎总是会导致问题。

没有任何东西需要同步。为什么要同步particleLock?同步在这里不起作用。您是syncronizing particleLock但您没有使用来自此对象的任何数据。particleLock的目的是什么?@hhafeez显然,他正在同步,这样他就不会在迭代数组的同时添加到数组中,从而消除ConcurrentModificationException的风险。但他没有同步arrya,arrya是实际的rE要同步的资源我看到了它的等价物,但没有必要为锁定义一个新的对象。你应该在不使用任何角度的情况下进行力计算。或者,如果出于某种传统原因必须使用角度,请使用
atan2
函数的幂函数来获得单位圆上的正确位置,这也是避免
asin
的参数接近1时出现奇点。我看不到代码中有任何线程参与,但如果存在,则肯定应该将数组声明为volatile!我尝试将其声明为volatile,但不起作用。我不确定我是否知道如何执行您所描述的操作。@NicolasMartorell您将哪个变量设置为volatile?