简体   繁体   English

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

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

I was trying to write a little gravity simulation program. 我试图编写一个重力模拟程序。 You specify a velocity and angle then it does the math and I used Java2D to draw it real time. 您指定速度和角度,然后进行数学计算,我使用Java2D实时绘制它。 The program itself works, I tested it out and it was beautiful. 该程序本身可以工作,我对其进行了测试,它很漂亮。 However, I did a little bit of restructuring for clarity purposes and now I'm having an issue. 但是,为了清晰起见,我进行了一些重组,现在遇到了问题。

Here is the intended behavior: The Gravity physics are all defined in its own class. 这是预期的行为:重力物理学都在其自己的类中定义。 This class basically has a timer that is constantly updating the coordinates taken as parameters. 此类基本上有一个计时器,该计时器不断更新作为参数的坐标。 I'm creating this class in the run() (threading) method of another class called Sprite. 我正在另一个名为Sprite的类的run()(线程)方法中创建此类。 The invoking class (being Sprite) can retrieve these updated coordinates using the methods I define called getX() and getY() in Gravity. 调用类(即Sprite)可以使用我在Gravity中定义的称为getX()和getY()的方法来检索这些更新的坐标。 So, once I create the gravity object in Sprite's run() method I have Sprite start an infinite that calls getX & getY methods and updates its own x & y coords. 因此,一旦我在Sprite的run()方法中创建了重力对象,我便让Sprite启动了一个调用getX和getY方法的无限对象并更新了自己的x和y坐标。

The issue is, even though the Gravity object and the infinite are on seperate threads, the infinite is freezing the gravity/updating. 问题是,即使Gravity对象和infinite在单独的线程上,infinite冻结了重力/更新。 Why is it doing this? 为什么这样做呢?

Gravity Class: 重力等级:

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);
        }

    }
}

Sprite Class: 精灵类:

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));
    }

}

How I initialize Sprite : 我如何初始化Sprite

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

Your gravity is in the same thread as your sprite. 您的重力与子画面位于同一线程中。

Your retriev method is called from a key event, which is waiting for the method to be done. 从关键事件中调用您的检索方法,该事件正在等待方法完成。 Do not use infinite loops for such things. 请勿对此类事情使用无限循环。

Gravity should be updated when sprite is updated (x time per second, see updates per second [UPS]). 精灵更新时应更新重力(每秒x时间,请参阅每秒更新[UPS])。 Usualy you will have more then one sprite at once and all of them have to be updated several times per second in a loop. 通常,您一次将拥有一个以上的子画面,并且所有这些子画面必须每秒循环更新几次。

You should use a seperated thread for ui and events: loot at SwingUtilities.invokeLater() 您应该对ui和事件使用单独的线程:在SwingUtilities.invokeLater()处获取战利品

It would be bette to create a controller class, which stors all the sprite objects and has a update thread, which runs at fixed update rate and call update method of each sprite. 可以创建一个控制器类,该类存储所有Sprite对象并具有一个更新线程,该线程以固定的更新速率运行,并调用每个Sprite的update方法。


EDIT: 编辑:

What you have at the moment is: 您目前所拥有的是:

A Thread, with a object (sprite) inside it, and a object (gravity) as a property of sprite. 一个线程,其中包含一个对象(精灵),一个对象(重力)作为精灵的属性。 Now inside of run you just create a new object (g) and then the tread ends up. 现在,在运行内,您只需创建一个新对象(g),然后胎面结束。

If you realy want for each sprite a own gravity thread, you havte to do something like this. 如果您确实要为每个子图创建自己的重力线,则必须这样做。

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

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

Using this, on calling Thread.start your sprite method will start to call retrieve. 使用此方法,在调用Thread.start时,您的sprite方法将开始调用检索。

A Thread allways has a main loop, when you cancle the loop, the tread stops working. 线程始终具有一个主循环,当您打开该循环时,胎面将停止工作。 In java the run method of Runnable is the start point for your loop, when a thread is ready with the run method, It stops working. 在Java中,Runnable的run方法是循环的起点,当线程已准备好run方法时,它将停止工作。 So all you want to do inside a new thread, has to be inside the run method. 因此,您想要在新线程内执行的所有操作都必须在run方法内。

Set a breakpoint in your method, retrieve() , that contains the infinite loop and run your program in a debugger. 在包含无限循环的方法retrieve()设置一个断点,然后在调试器中运行程序。 You'll see that you call retrieve() from within keyPressed() , which is called by the Swing toolkit on the AWTEventQueue thread. 您会看到您从keyPressed()内调用retrieve() ,该方法由AWTEventQueue线程上的Swing工具包调用。 Your infinite loop is on the event dispatch thread and so no more events (including Swing timers) can be processed. 您的无限循环位于事件分配线程上,因此无法处理更多事件(包括Swing计时器)。

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

相关问题 为什么我的线程即使在无限循环中也只能执行一次? - Why my thread only execute once even if its in an infinite loop? 为什么我的 IDE 说我的一段代码没有扩展其超类的方法,即使它是? - Why does my IDE say my piece of code isnt extending a method of its superclass, even though it is? 为什么我的Java代码导致Netbeans冻结 - Why does my Java code cause netbeans to freeze 为什么我的 java 项目在缺少一些包的情况下仍然有效? - Why does my java project still work even though its missing some packages? 当我尝试添加ArrayList元素时,即使它是新的,为什么我的程序仍然存在? - Why does my program say the ArrayList element exists when I try to add it even though it's new? 为什么线程会冻结我的actionListener实现中的代码? - Why does the thread freeze my code in my actionListener implementation? 为什么我的 AsyncTask 冻结了我的 UI 线程? - Why does my AsyncTask freeze my UI Thread? 为什么我的异常处理中的错误会导致无限循环? - Why does my error my exceptions handling cause an infinite loop? 为什么这会导致无限循环 - Why does this cause an infinite loop 为什么即使没有任何错误,编译器也不会运行程序? - Why does the compiler not run the program even though there are not any errors?
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM