繁体   English   中英

为什么我的infinite导致程序的其余部分冻结,即使它位于单独的线程上也是如此?

[英]Why does my infinite cause the rest of the program to freeze even though its on a separate thread?

我试图编写一个重力模拟程序。 您指定速度和角度,然后进行数学计算,我使用Java2D实时绘制它。 该程序本身可以工作,我对其进行了测试,它很漂亮。 但是,为了清晰起见,我进行了一些重组,现在遇到了问题。

这是预期的行为:重力物理学都在其自己的类中定义。 此类基本上有一个计时器,该计时器不断更新作为参数的坐标。 我正在另一个名为Sprite的类的run()(线程)方法中创建此类。 调用类(即Sprite)可以使用我在Gravity中定义的称为getX()和getY()的方法来检索这些更新的坐标。 因此,一旦我在Sprite的run()方法中创建了重力对象,我便让Sprite启动了一个调用getX和getY方法的无限对象并更新了自己的x和y坐标。

问题是,即使Gravity对象和infinite在单独的线程上,infinite冻结了重力/更新。 为什么这样做呢?

重力等级:

public class Gravity implements ActionListener { // create me in a run() method
                                                    // for a new thread
    final double gravAccel = -32.174;
    double velocity; // in FPS
    double angle; // in degrees
    double x; // centralized location of object in feet
    double y; // centralized location in feet
    double time = 0;
    Timer timer;
    boolean fired = true;
    Point start;

    public Gravity(double x, double y, double velocity, double angle, Point start) {
        this.x = x;
        this.y = y;
        this.velocity = velocity;
        this.angle = angle;
        this.start = start;
        initTimer();
    }



    void initTimer() {
        timer = new Timer(10, this);
        timer.start();
    }   


    public void fire(double velocity, double angle) {
        //timer.start();
        x = (velocity * Math.cos(Math.toRadians(angle))) * time + start.getX();
        y = 0.5 * gravAccel * Math.pow(time, 2) + (velocity * Math.sin(Math.toRadians(angle))) * time + start.getY();
        System.out.println("Time:" + time + "          " + x + "," + y);

    }


    public double getX() {
        return x;
    }
    public double getY() {
        return y;
    }

    @Override
    public void actionPerformed(ActionEvent e) {
        time = time + 0.01;
        if (fired == true) {
            fire(velocity, angle);
        }

    }
}

精灵类:

public class Sprite implements KeyListener, Runnable {
    public Dimension hitbox;
    double startX = 30;
    double startY = 30;
    double x = startX; // centralized location of object in feet
    double y = startY; // centralized location in feet

    Gravity g;

    public Sprite() {
        hitbox = new Dimension(1, 1);
    }

    @Override
    public void keyPressed(KeyEvent e) {
        // TODO Auto-generated method stub
        int i = e.getKeyCode();
        if (i == KeyEvent.VK_SPACE) {

            retrieve();

        }

    }

    @Override
    public void keyReleased(KeyEvent arg0) {
        // TODO Auto-generated method stub

    }

    @Override
    public void keyTyped(KeyEvent arg0) {
        // TODO Auto-generated method stub

    }

    public void retrieve() {
       for(;;){                                   
        x = g.getX();
        y = g.getY();
      }
    }

    @Override
    public void run() {
        // TODO Auto-generated method stub
        g = new Gravity(x, y, 50, 70, new Point((int) startX, (int) startY));
    }

}

我如何初始化Sprite

Sprite s = new Sprite();
Thread t = new Thread(s);
t.start();

您的重力与子画面位于同一线程中。

从关键事件中调用您的检索方法,该事件正在等待方法完成。 请勿对此类事情使用无限循环。

精灵更新时应更新重力(每秒x时间,请参阅每秒更新[UPS])。 通常,您一次将拥有一个以上的子画面,并且所有这些子画面必须每秒循环更新几次。

您应该对ui和事件使用单独的线程:在SwingUtilities.invokeLater()处获取战利品

可以创建一个控制器类,该类存储所有Sprite对象并具有一个更新线程,该线程以固定的更新速率运行,并调用每个Sprite的update方法。


编辑:

您目前所拥有的是:

一个线程,其中包含一个对象(精灵),一个对象(重力)作为精灵的属性。 现在,在运行内,您只需创建一个新对象(g),然后胎面结束。

如果您确实要为每个子图创建自己的重力线,则必须这样做。

public Sprite(){
  //do what you want to
  g = new Gravity(...);
}

public void run(){
  while(true){
    retrieve();
  }
}

使用此方法,在调用Thread.start时,您的sprite方法将开始调用检索。

线程始终具有一个主循环,当您打开该循环时,胎面将停止工作。 在Java中,Runnable的run方法是循环的起点,当线程已准备好run方法时,它将停止工作。 因此,您想要在新线程内执行的所有操作都必须在run方法内。

在包含无限循环的方法retrieve()设置一个断点,然后在调试器中运行程序。 您会看到您从keyPressed()内调用retrieve() ,该方法由AWTEventQueue线程上的Swing工具包调用。 您的无限循环位于事件分配线程上,因此无法处理更多事件(包括Swing计时器)。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM