0

I have a weird issue, where I'm trying to make a program which is using a thread to implement a tick update system, using the following code:

@Override
public void run(){
    long lastTime = System.nanoTime();
    long deltaTime;
    float passedTime = 0;
    long ticks = 0;

    while(true){
        long currentTime = System.nanoTime();

        deltaTime = currentTime - lastTime;
        lastTime = currentTime;

        passedTime += deltaTime / tickTime;

        if(passedTime * 20 > ticks){
            ticks++;
            tick();

            System.out.println(ticks);
        }
    }
}

This works fine, except for the fact that after exactly 161 ticks it simply ceases to run, it doesn't throw anything, no exceptions, no errors, nothing. However as soon as I do the following:

@Override
public void run(){
    long lastTime = System.nanoTime();
    long deltaTime;
    float passedTime = 0;
    long ticks = 0;
    long useless = 0;

    while(true){
        long currentTime = System.nanoTime();

        deltaTime = currentTime - lastTime;
        lastTime = currentTime;

        //Don't focus on this bit, I know it's a bit odd.
        passedTime += deltaTime / tickTime;

        if(passedTime * 20 > ticks){
            ticks++;
            tick();

            System.out.println(ticks);
        }

        useless++;
        System.out.print(useless);
    }
}

And now suddenly it runs with no problem?

Does anyone have any idea what this could be due to? Thanks in advance!

SchoolJava101
  • 609
  • 1
  • 5
  • 8
  • What does your method `tick()`? – SubOptimal Sep 20 '16 at 09:43
  • 1
    It's possible that the JVM has optimized te execution of the loop after the first 161 iteration to the point where `deltaTime < tickTime` and if `tickTime` is an integral type, this leads 0 always being added... – fabian Sep 20 '16 at 09:45
  • @SubOptimal it calls all the update methods for the program, at the moment it onlu calls a method which does calculations on gravitational attraction between some objects. – SchoolJava101 Sep 20 '16 at 09:49
  • @fabian Thanks, I'll try change some types around and see if it works. – SchoolJava101 Sep 20 '16 at 09:50
  • what is the value of tickTime? I use the first code and run without any problem...You add System.out makes passedTime larger. – fairjm Sep 20 '16 at 09:53
  • Hi SchoolJava101, embed your code in try{} catch{} block and catch Exception and printStackTrace() – Ravindra babu Sep 20 '16 at 10:36
  • @Ravindra Babu, I tried to do that initially by catching any Throwable and nothing happened, I think OldCurmudgeon may be right, I'm going to test. – SchoolJava101 Sep 20 '16 at 10:40

1 Answers1

2

The reason adding just a print statement fixes the iussue is because you are spinning.

If a thread performs a tight loop with no blocking/io/other it will just spin and hog the cpu, causing all other polite threads to get fewer resources.

To get around this (as a temporary measure) you could add a Thread.sleep(0) which will release the cpu for other threads to get cpu time.

A more permanent solution should be to put together some mechanism to communicate between your process (perhaps a BlockingQueue) so your thread spends most of it's time waiting/blocking.

OldCurmudgeon
  • 64,482
  • 16
  • 119
  • 213
  • If this is only used for timing in the program, and there is no need for inter-thread communication, would a BlockingQueue still be ideal? Would you be able to recommend any good tutorials? Thanks again! – SchoolJava101 Sep 20 '16 at 10:36
  • @SchoolJava101 - You could consider a [TimerTask](https://docs.oracle.com/javase/7/docs/api/java/util/TimerTask.html) if it's just timing you need. – OldCurmudgeon Sep 20 '16 at 11:53
  • @SchoolJava101 - Also a [ScheduledThreadPoolExecutor](https://docs.oracle.com/javase/7/docs/api/java/util/concurrent/ScheduledThreadPoolExecutor.html) could be a more flexible option. – OldCurmudgeon Sep 20 '16 at 12:16