Search code examples
javamultithreadingsynchronizationshared-memoryvolatile

Java: Volatile variable not updating (get and set methods not working)


I have a Runnable "NanoClock" class which keeps updating a private volatile double value in its run() method.

This class also has a getTime() method which returns the double value. Another class ("Master") is constructing the NanoClock class and creates a thread, as well as calling the start() method.

After it did this it calls the getTime() method several times (with a delay), but the value is not updating. What am I doing wrong?

NanoClock.java :

public class NanoClock implements Runnable {
    private volatile boolean running;
    private volatile double time;
    public NanoClock() {
        time = System.currentTimeMillis();
    }
    @Override
    public void run() {
        running = true;
        while(running) {
            try {
                if(System.currentTimeMillis() > time) {
                    time = System.currentTimeMillis();
                }
              //This returns the updated value continuously when commented out
              //System.out.println("Time: " + String.format("%.6f", unix_time));
                Thread.sleep(2000);
            } catch(Exception exc) {
                exc.printStackTrace();
                System.exit(1);
            }
        }
    }
    public double getTime() {
        return time;
    }
    public void end() {
        running = false;
    }
}

Master.java:

public class Master {
    public static void main(String[] args) {
        try {
            NanoClock nClock = new NanoClock();
            Thread clockThread = new Thread(new NanoClock());
            clockThread.setPriority(10);
            clockThread.start();
            //MY_ISSUE: This returns the same value every time
            for(int a = 0; a < 10; a++) {
                System.out.println("Time: " + nClock.getTime());
            }
            //MY_ISSUE: This cannot stop the while loop - I tested it with 
            //the println in the NanoClock class.
            nClock.end();
            System.out.println("Done!");
        catch(Exception e) {
            e.printStackTrace();
            System.exit(1);
        }
    }
}

Solution

  • You've got two instances of NanoClock: one of them is an anonymous new NanoClock() which, as the Runnable in your other thread is happily keeping time in the backgound; the other is nClock, which is sitting idly by in the foreground in your main thread.

    nClock should have been the Runnable in that other thread:

    Thread clockThread = new Thread(nClock);  // not new NanoClock()
    

    This may not be the entire solution, but it should be a big step in the right direction.