Thread.sleep() in while loop doesn't work properly?

|▌冷眼眸甩不掉的悲伤 提交于 2019-12-25 07:59:43

问题


The object is supposed to change modes (movement algorithm) every 5 seconds. I first tried with a while loop but the loop was iterating way too fast. Then I added Thread.sleep(5000) but still my object moves only in one algorithm (scatterMode). Here is the algorithm:

//LEVEL 1
//scatter for 7s 
//chase for 20s 
//scatter for 7s 
//chase for 20s 
//scatter for 5s 
//chase for 20s
//scatter for 5s 
//chase indefinite

And here is the code. The constructor and variable declarations are at the bottom if you need to see them.

public void updateMode() throws InterruptedException {  
    while(ghostalive){
        if(seconds<7){
            Thread.sleep(100);
            mode = scatterMode;
        }
        if(7<seconds && seconds<27){
            Thread.sleep(5000);
            mode = chaseMode;
        }
        if(27<seconds && seconds<34){
            Thread.sleep(5000);
            mode = scatterMode;
        }
        if(34<seconds && seconds<54) {
            Thread.sleep(5000);
            mode = chaseMode;
        }
        if(54<seconds && seconds>59) {
            mode = scatterMode;
        }
        if(59< seconds && seconds<79){
            mode = chaseMode;
        }
        if(seconds>84){
            mode = scatterMode;
            ghostalive=false;
        }
        seconds++;
        ghostalive=false;
    }
}

private int seconds=0;
private boolean ghostalive=true;

protected static final int chaseMode = 0;
protected static final int scatterMode = 1;

static int mode = scatterMode; //initially ghost start in scatterMode

public Ghost(int x, int y, Maze maze) throws InterruptedException{
    super(x, y, maze);
    futureDirection = 0;
    timer = 0;
    updateMode();
    //chaseMode = false; 
    //frightenedMode = false;
}     

public static int getMode(){
    return mode;
}

回答1:


Your sleep pattern is mixture of milliseconds and several seconds, but you are expecting to count seconds.

Try something like this:

while(ghostalive){

    if(seconds<7){
        mode = scatterMode;

    }

    if(7<seconds && seconds<27){
        mode = chaseMode;
    }

    if(27<seconds && seconds<34){
        mode = scatterMode;
    }

    if(34<seconds && seconds<54) {
        mode = chaseMode;
    }

    if(54<seconds && seconds>59) {
        mode = scatterMode;
    }

    if(59< seconds && seconds<79){
        mode = chaseMode;
    }

    if(seconds>84){
        mode = scatterMode;
        ghostalive=false;
    }

    seconds++;
    Thread.Sleep(1000);//Sleep for one second only

    //ghostalive=false; // Should this be here? Ghost is set to not alive after each loop?
}

I have moved the sleep after the if statements so that it is consistent in each loop.




回答2:


I think you should not rely on Sleep for measuring time because it can behave differently everytime you run it. Thread can goto sleep for more than the mentioned time. Sleep only pauses current thread for specific time. It does not guarantees that this thread will start executing again after same time.




回答3:


Do NOT invoke updateMode from the constructor.

Instead, start a new thread.

As of now, probably the following happens: your Ghost is creates, goes through all of his stages before the constructor is complete. Then when your main program starts, your ghost is ghostalive=false and in scatterMode already.

For debugging, put in a lot of Loggin statements. It's best to use the logging APIs, but many beginners prefer System.out.println. It is a good practise to just print what you are doing - i.e. which mode you set the ghost to.

When you then also add game timer things, you should easily see that the ghost first goes through all of his states, before your actual game even started (i.e. a "game has started" logging is also a must.

Logging is not at all more difficult than printing.

// for each class, add such a line:
private static final LOG = java.util.logging.Logger.getLogger("packagename.classname");

static {
  // Configure the active logging level manually
  // For larger projects, use a .properties file!
  LOG.setLevel(java.util.logging.Level.ALL);
}

// inside of appropriate methods, use
if (LOG.isLoggable(Level.DEBUG)) {
  LOG.log(Level.DEBUG, "My ghost is now frightened.");
}

The if statement is important. It can be optimized well by hotspot, so that if logging is disabled, the logging statements come at next to no cost.

The good thing is that you can turn on and off these statements easily. While System.out.println you have to manually remove and readd to your code.




回答4:


When seconds is exactly 7 or 34 or 54,..., there is no condition to handle these cases. It just doesn't enter in any of the if statements.



来源:https://stackoverflow.com/questions/13402703/thread-sleep-in-while-loop-doesnt-work-properly

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!