1

我正在用 Java 制作一个 2D 物理游戏,最近决定完全重新开始,以便程序的基础具有灵活性和线程化。我的问题是找到一种在程序运行期间存储我的游戏数据的方法,同时考虑到线程。

我以前用于存储数据的库看起来像这样

public float[] sphereX = new float[sphereNum];
public float[] sphereY = new float[sphereNum];
public float[] sphereXMem = new float[sphereNum];
public float[] sphereYMem = new float[sphereNum];
public float[] sphereVX = new float[sphereNum]; // X Velocity
public float[] sphereVY = new float[sphereNum]; // Y Velocity

// Misc Variables
public float[] sphereMass = new float[sphereNum];
public float[] sphereRadius = new float[sphereNum];

虽然这对于没有线程和较少功能的程序来说是件好事,但我当前的程序将有几个新的需求,这是以前的版本没有解决的。这些包括:

  • 球体的数量不断变化
  • Spheres 有更多的数据类型。(布尔型、整数型和浮点型)
  • 此游戏数据正在被多个线程不断访问和修改

我担心在锁定密钥可用之前将线程锁定在数据之外会显着减慢程序的速度,因为大约 1-4 个线程将在计算所有物理时忙于工作。

我目前对解决方案的想法是拥有一个包含该对象参数数组的对象的 Arraylist,但我不知道如何使用线程来实现它。

正如您可能猜到的,我对线程有些陌生,但知道波动性和基本同步的基本概念。另外,如果您想知道,我正在使用线程来希望我的程序能够利用多个内核。

编辑:从评论中考虑后,我想出了这个。这是正确的吗?一开始我并不打算创建一个单独的类,但这可能是最好的。问这个我觉得很愚蠢,但是如果我将所有信息放在一个单独的文件中,它会保留它的信息吗?由此,我只需在主类中的 ArrayList 中添加多个项目(项目是新的球体)?

enter code here`public class Item 
{
    private Object lockActive = new Object();
    private Object lockType = new Object();
    private Object lockMass = new Object();
    private Object lockLocation = new Object();
    private Object lockLocationMemory = new Object();
    private Object lockVelocity = new Object();

    private boolean active;
    private int type;
    private float mass;
    private float[] location;
    private float[] locationMemory;
    private float[] velocity;

    public Item(boolean active, int type, float mass, float[] location, float[] locationMemory, float[] velocity) 
    {
        this.active = active;
        this.type = type;
        this.mass = mass;
        this.location = location;
        this.locationMemory = locationMemory;
        this.velocity = velocity;
    }

    public boolean GetActive() 
    {
        synchronized (lockActive)
        {
            try
            {
                Thread.sleep(1);
            }
            catch(InterruptedException e)
            {
                e.printStackTrace();
            }
            return active;
        }
    }

    public synchronized int GetType() 
    {
        synchronized (lockType)
        {
            try
            {
                Thread.sleep(1);
            }
            catch(InterruptedException e)
            {
                e.printStackTrace();
            }
            return type;
        }
    }

    public synchronized float GetMass() 
    {
        synchronized (lockMass)
        {
            try
            {
                Thread.sleep(1);
            }
            catch(InterruptedException e)
            {
                e.printStackTrace();
            }
            return mass;
        }
    }

    public synchronized float[] GetLocation() 
    {
        synchronized (lockLocation)
        {
            try
            {
                Thread.sleep(1);
            }
            catch(InterruptedException e)
            {
                e.printStackTrace();
            }
            return location;
        }
    }

    public synchronized float[] GetLocationMemory() 
    {
        synchronized (lockLocationMemory)
        {
            try
            {
                Thread.sleep(1);
            }
            catch(InterruptedException e)
            {
                e.printStackTrace();
            }
            return locationMemory;
        }
    }

    public synchronized float[] GetVelocity() 
    {
        synchronized (lockVelocity)
        {
            try
            {
                Thread.sleep(1);
            }
            catch(InterruptedException e)
            {
                e.printStackTrace();
            }
            return velocity;
        }
    }

    public void SetActive() 
    {
        synchronized (lockActive)
        {
            try
            {
                Thread.sleep(1);
            }
            catch(InterruptedException e)
            {
                e.printStackTrace();
            }
            this.active = active;
        }
    }

    public void SetType(int type) 
    {
        synchronized (lockType)
        {
            try
            {
                Thread.sleep(1);
            }
            catch(InterruptedException e)
            {
                e.printStackTrace();
            }
            this.type = type;
        }
    }

    public void SetMass(float mass) 
    {
        synchronized (lockMass)
        {
            try
            {
                Thread.sleep(1);
            }
            catch(InterruptedException e)
            {
                e.printStackTrace();
            }
            this.mass = mass;
        }
    }

    public void SetLocation(float[] location) 
    {
        synchronized (lockLocation)
        {
            try
            {
                Thread.sleep(1);
            }
            catch(InterruptedException e)
            {
                e.printStackTrace();
            }
            this.location = location;
        }
    }

    public void SetLocationMemory(float[] locationMemory) 
    {
        synchronized (lockLocationMemory)
        {
            try
            {
                Thread.sleep(1);
            }
            catch(InterruptedException e)
            {
                e.printStackTrace();
            }
            this.locationMemory = locationMemory;
        }
    }

    public void SetVelocity(float[] velocity) 
    {
        synchronized (lockVelocity)
        {
            try
            {
                Thread.sleep(1);
            }
            catch(InterruptedException e)
            {
                e.printStackTrace();
            }
            this.velocity = velocity;
        }
    }

}
4

1 回答 1

4

不要对自己那样做。与其为每个属性创建一个数据结构,不如定义一个球体对象来保存球体的所有属性。编写同步方法,以便多个线程不会一次更改单个球体。

这是一个快速而肮脏的开始:

//Sphere.java
public class Sphere {
    private float[] position;
    private float[] mem; 
    private float[] velocity;

    public Sphere(float[] position, float[] mem,  float[] velocity) {
        this.position = position;
        this.mem = mem;
        this.velocity = velocity;
    }

    public synchronized float[] getPosition() {
        return position;
    }
    public synchronized float[] getVelocity() {
        return velocity;
    }

    public synchronized void move() {
        position[0]+=velocity[0];
        position[1]+=velocity[1];
    }
}

然后你可以在其他地方初始化你的数据:

    int sphereCount = 30;
    List<Sphere> spheres = new ArrayList<Sphere>();
    Random rand = new Random();
    for( int i = 0; i < sphereCount; i++) {
        spheres.add(
            new Sphere(
                new float[]{20*rand.nextFloat(), 20*rand.nextFloat()}, //position
                new float[]{20*rand.nextFloat(), 20*rand.nextFloat()}, //mem
                new float[]{2*rand.nextFloat(), 2*rand.nextFloat()} //velocity
            )
        );
    }

同样,这只是粗略、模糊的代码,我没有考虑太多。这里的主要想法是使用对象来描述“事物”,以便您可以将所有细节代码用于在这些对象中以及在其余代码中操作它们。

至于synchronized关键字,它意味着该方法中的所有内容都发生在对同一对象的任何其他同步方法调用之前或之后。

于 2013-05-28T23:45:09.550 回答