Java 定期更新静态变量的正确方法

Java 定期更新静态变量的正确方法,java,Java,我有一个静态变量,我在类的开头加载它。我想每小时更新一次变量。问题是这样做的正确方式是什么 我尝试这样做的方式如下,但它需要在每个构造函数中更新静态变量的方法: import java.util.Date; public class MyClass { private static String globalString = ""; // initialize lastUpdate with two hours back to make sure first update

我有一个静态变量,我在类的开头加载它。我想每小时更新一次变量。问题是这样做的正确方式是什么

我尝试这样做的方式如下,但它需要在每个构造函数中更新静态变量的方法:

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();
        }
    }
}

还有其他更好的方法吗?

你应该使用某种计时器来进行更新

例如,使用ScheduledExecutorService每小时运行一次任务,这会更新字段。大概是这样的:

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
    ...
}
请注意,由于变量由多个线程访问,因此需要确保代码是线程安全的。(上面的计时器示例肯定是这样,但您当前的方法也可能是这样。)


确保看到更新的最简单方法是将
globalString
变量标记为
volatile
,但根据类的使用方式,其他方法可能更合适。

您应该使用某种计时器来进行更新

例如,使用ScheduledExecutorService每小时运行一次任务,这会更新字段。大概是这样的:

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
    ...
}
请注意,由于变量由多个线程访问,因此需要确保代码是线程安全的。(上面的计时器示例肯定是这样,但您当前的方法也可能是这样。)


确保看到更新的最简单方法是将
globalString
变量标记为
volatile
,但根据类的使用方式,其他方法可能更合适。

一个简单的解决方案是使用Executors框架:

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);
   } 
}

一个简单的解决方案是使用Executors框架:

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);
   } 
}

您可以使用来计划每小时运行一个任务。如果您有一个缓存库来处理一个条目的有效时间跨度,而不是对其进行编程,那就更好了。您可以使用构造函数链接,在第一个构造函数中放入
updateGlobalString()
,然后使用
this()调用其他项。您可以使用来计划每小时运行一个任务。如果您有一个缓存库来处理一个项的活动时间跨度,而不是对其进行编程,那就更好了。您可以使用构造函数链接,在第一个构造函数中放入
updateGlobalString()
,然后使用
this()呼叫其他人。使用
60*60秒的时间段
似乎缺少
时间单位
..)+1不管怎样-你以前的东西没有什么问题,它确实有效,它只是让我微笑。使用
60*60秒的时间段
似乎忽略了
时间单位
…)+1不管怎么说,你以前所拥有的一切都没有问题,它确实有效,它只会让我微笑。这是一个很好的方法。从我的想法来看,肯定好多了。如果您不介意的话,还有一个问题:为什么ScheduledExecutorService是在类级别定义的,而不仅仅是在静态块中定义的,因为静态块在开始时只执行一次?我想这是有充分理由的。奇怪的是,还有一个问题是,如果类被多个线程访问,该怎么办?此方法将给出IllegalMonitorStateException。对吗?@user2287359我在类级别声明了executor服务,因为我认为这样更清楚(无论哪种方式都有一个静态executor服务)。另外,这意味着,如果您出于任何原因想要停止未来的更新,那么您将有一个对它的引用。至于您的
IllegalMonitorStateException
问题,只有在您尝试调用
obj.wait()
obj.notify()
而不按住
obj
的监视器(即在其上同步)时,才会引发此异常。我的代码不需要这些方法,而是使用执行器,因此在任何情况下都不应该抛出异常。这是一个很好的方法。从我的想法来看,肯定好多了。如果您不介意的话,还有一个问题:为什么ScheduledExecutorService是在类级别定义的,而不仅仅是在静态块中定义的,因为静态块在开始时只执行一次?我想这是有充分理由的。奇怪的是,还有一个问题是,如果类被多个线程访问,该怎么办?此方法将给出IllegalMonitorStateException。对吗?@user2287359我在类级别声明了executor服务,因为我认为这样更清楚(无论哪种方式都有一个静态executor服务)。另外,这意味着,如果您出于任何原因想要停止未来的更新,那么您将有一个对它的引用。至于您的
IllegalMonitorStateException
问题,只有在您尝试调用
obj.wait()
obj.notify()
而不按住
obj
的监视器(即在其上同步)时,才会引发此异常。我的代码不需要这些方法,而是使用执行器,因此在任何情况下都不应该抛出该异常。