代码有时可以运行但其他代码运行(内存或线程问题)

时间:2012-12-25 18:04:36

标签: java multithreading swing

我遇到了这个奇怪的问题,我不确定是什么导致了这个问题。有时问题甚至不存在。根据我的猜测,这是一个Java内存问题或某种线程问题。

我有Ship并且船只射击Bullets如果我按住 Space 键,船会射击子弹。我的子弹每隔200毫秒开始发射一次。有时他们射击很好,并以相同的速度移动!其他时候,他们射击他们以不同的速度移动。什么可能导致这种情况?

package JGame.Actions;

import JGame.GameObject.GameObject;
import javax.swing.AbstractAction;

public class MoveAction extends Action implements Runnable{

    protected GameObject obj;
    protected int endX = 0, endY = 0;
    protected int moveAmount = 0;
    protected Thread thread;

    public void moveToY(GameObject obj, int y, int amount, AbstractAction complete){
        this.obj = obj;
        this.endY = y;
        this.moveAmount = amount;
        this.complete = complete;
        thread = new Thread(this);
        thread.start();
    }

    public void run(){
        try{
            boolean run = true;
            while(run){
                int objY = obj.getY();
                if(objY > this.endY){
                    obj.setY(obj.getY() - 1);
                }else if(objY < this.endY){
                    obj.setY(obj.getY() + 1);
                }else{
                    run = false;
                    this.actionComplete();
                }
                thread.sleep(moveAmount);
            }
        }catch(Exception e){
        }
    }
}

行动完成:

package JGame.Actions;

import javax.swing.AbstractAction;

public class Action {
    protected boolean actionComplete = false;
    protected AbstractAction complete;

    public void actionComplete(){
        complete.actionPerformed(null);
    }
}

在我的代码中,我调用moveToY这是一个非常简单的调用,但有时Bullets以不同的速度移动(错误),而其他时候它们以相同的速度移动(右)。我不知道是否有必要提一下,随着子弹移动,有时它们会减速一两秒,然后速度恢复到正确的速度。

编辑:主线程

以下是我使用paintComponent的主线程

@Override
public void run(){
    try{
        while(true){
            // Check for key press events
            Iterator actions = KeyboardMap.map.entrySet().iterator();
            while(actions.hasNext()){
                Map.Entry ap = (Map.Entry)actions.next();
                Mapping mp = (Mapping)ap.getValue();
                if(mp.pressed){
                    mp.run();
                }
            }

            // Check for click mouse events
            Iterator actions2 = MouseMap.map.entrySet().iterator();
            while(actions2.hasNext()){
                Map.Entry ap = (Map.Entry)actions2.next();
                Mapping mp = (Mapping)ap.getValue();
                if(mp.pressed){
                    mp.run();
                }
            }

            for(GameObject go : gameObjects){
                if(!go.getLeaveScreen()){
                    int goWidth = go.getWidth();
                    int goHeight = go.getHeight();
                    int goX = go.getX();
                    int goY = go.getY();
                    int gameWidth = Game.width;
                    int gameHeight = Game.height;
                    if(goX + goWidth >= gameWidth){
                        go.setX(gameWidth - goWidth);
                    }
                    if(goX <= 0){
                        go.setX(0);
                    }
                    if(goY + goHeight >= gameHeight){
                        go.setY(gameHeight - goHeight);
                    }
                    if(goY <= 0){
                        go.setY(0);
                    }
                }
            }
            this.repaint();
            Thread.sleep(roomSpeed);
        }
    }catch(Exception e){
    }
}

public void paintComponent(Graphics g){
    try{
        g.drawImage(bg, 0, 0, this);
        for(int i = 0; i < gameObjects.size(); i++){
            GameObject go = gameObjects.get(i);
            g.drawImage(go.getSprite(), go.getX(), go.getY(), this);
        }
    }catch(Exception e){
    }
}

3 个答案:

答案 0 :(得分:5)

好吧,我猜你有很多并发线程正在运行(一个是移动子弹),你希望每个线程在moveAmount毫秒之后唤醒。你不能有这样的保证,因为线程调度程序允许每个线程一次运行一个时间,因此你可能会有毛刺。

另一个问题是,您似乎在事件派发线程中对Swing组件执行了修改,Swing's threading policy明确禁止这样做。

答案 1 :(得分:1)

在代码中更改最重要的是不要使用Thread.sleep 建模时间。使用 Swing Timer ,您计划每隔moveAmount毫秒执行一次,作为奖励,代码将在事件调度线程上执行,而您无需付出任何努力。

答案 2 :(得分:0)

告知您自己多线程的使用情况以及如何正确处理游戏的处理结构。 您案例最重要的信息:您应该只使用一个线程来处理/移动所有子弹,然后渲染它们。