确保在使用任何静态方法之前初始化静态变量?

时间:2014-02-10 03:33:23

标签: java concurrency

我有一个监视器类,其中包含一个名为ClockValues的静态(和final}变量。每个其他静态方法都使用此变量。但是,ClockValues对象来自外部源。在使用此类中的任何静态方法之前,我是否可以确保外部对象和线程初始化ClockValues? 有点像构造函数,但对于静态变量。

public class SharedData {
    private static final MutexSem   mutex = new MutexSem();
    private static ClockValues  clock;

    //my static "Constructor"
    //but I can't force other objects to call this method before all other methods in this class
    //I understand I could use a flag to signal initilization, but I was looking for a cleaner way
    public static  void initialize(ClockValues c){
        mutex.take();
        clock= c;
        mutex.give();
    }

    public static void doSomething(){
        mutex.take();
        //do something with `clock`
        mutex.give();
    }

//... more methods using `clock` variable


}

2 个答案:

答案 0 :(得分:0)

我认为你不能用静态方法做你想做的事。您可以使用单例模式执行某些操作:

public class SharedData {
    private static final MutexSem  mutex = new MutexSem();
    private static SharedData instance;
    private ClockValues clock;

    public static SharedData getInstance(ClockValues c) {
        mutex.take();
        if (instance == null) {
            instance = new SharedData(c);
        }
        mutex.give();
        return instance;
    }

    private SharedData(ClockValues c) {
        clock = c;
    }

    public void doSomething() { // NOTE: no longer static
        mutex.take();
        //do something with `clock`
        mutex.give();
    }

    //...
}

不幸的是,这需要每次调用getInstance都有一个ClockValues值作为参数传递。但是,根据您的架构,这可能是一种可行的替代方案。

答案 1 :(得分:0)

初始化单例的标准模式在Effective Java, Second Edition, Item 71

中描述
public class AService {
  private static int init = 0;
  private static class Holder {
    private static final AService theService = new AService(init);
  }

  private AService(int init) {
    System.out.println("AService instance initialized with " + init);
  }

  public static AService instance(int init) {
    AService.init = init;
    return Holder.theService;
  }
}

因此,服务单例的实例化被延迟,直到第一次调用实例(可能需要额外的参数等),并且您可以执行更复杂的实例化。根据您的项目初始化逻辑,您可以将.instance(init)分为.getFirstInstance(init).instance(),但这完全取决于您。