簡體   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