简体   繁体   中英

Proper way to update static variable periodically

I have a static variable that I load at the beginning of a class. I want to update the variable every hour. The question is what is the proper way of doing this?

The way I am trying to do it is the following but it requires the method that updates the static variable to be in every constructor:

import java.util.Date;

public class MyClass {

    private static String globalString = "";

    // initialize lastUpdate with two hours back to make sure first update happens
    private static Date lastUpdate = new Date(System.currentTimeMillis() - (2 * (3600 * 1000)));


    MyClass() {
        updateGlobalString();

        // DO MORE STUFF HERE...
    }


    MyClass(String string) {
        updateGlobalString();

        // DO MORE STUFF HERE...
    }

    private synchronized void updateGlobalString() {
        // check if we need to update
        if (lastUpdate.before(new Date(System.currentTimeMillis() - (3600 * 1000)))) {

            // DO THINGS TO UPDATE globalString HERE...

            lastUpdate = new Date();
        }
    }
}

Any other ideas/better way of doing it?

You should use some sort of timer to do the update.

For example, use a ScheduledExecutorService to have a task run every hour, which updates the field. Something like this:

public class MyClass {

    private static volatile String globalString;
    private static ScheduledExecutorService exec = Executors.newSingleThreadScheduledExecutor();

    static {
        exec.scheduleAtFixedRate(new Runnable() {
            public void run() {
               // DO THINGS TO UPDATE globalString HERE...
            }
        },
        0, 1, TimeUnit.HOUR);
    }

    // Rest of class, without having to worry about the updateGlobalString
    // method, or the lastUpdate variable, or anything like that
    ...
}

Note that because the variable is being accessed by multiple threads, you'll need to ensure that your code is threadsafe. (This is definitely the case with the timer example above, but is likely to be the case with your current approach too.)

The easiest way to simply ensure that updates are seen is to mark the globalString variable as volatile , but depending on how the class is used other approaches may be more appropriate.

A simple solution is to use the Executors framework:

public class MyClass {
   public static String globalString = "";

   private static ScheduledExecutorService s = Executors.newSingleThreadScheduledExecutor();

   //static block of code
   static {
     s.scheduleAtFixedRate(new Runnable() {
        public void run() {
           globalString = System.currentTimeMillis() + "";
        }
     }, 0, 1, TimeUnit.HOUR);
   } 
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM