单例对象属性的更新--影子实例

通常,为了实现配置信息的实时更新,会有一个线程不停检测配置文件或配置数据库的内容,一旦发现变化,就更新到单例对象的属性中。在更新这些信息的时候,很可能还会有其他线程正在读取这些信息,造成意想不到的后果。还是以通过单例对象属性停止线程服务为例,如果更新属性时读写不同步,可能访问该属性时这个属性正好为空(null),程序就会抛出异常。

有两种方法:

1,参照读者/写者的处理方式

设置一个读计数器,每次读取配置信息前,将计数器加1,读完后将计数器减1。只有在读计数器为0时,才能更新数据,同时要阻塞所有读属性的调用。代码如下

public class GlobalConfig {
  private static GlobalConfig instance;
  private Vector properties = null;
  private boolean isUpdating = false;
  private int readCount = 0;
  private GlobalConfig() {
    //Load configuration information from DB or file
    //Set values for properties
  }
  private static synchronized void syncInit() {
      if (instance == null) {
          instance = new GlobalConfig();
      }
  }
  public static GlobalConfig getInstance() {
      if (instance==null) {
          syncInit();
      }
      return instance;
  }
  public synchronized void update(String p_data) {
      syncUpdateIn();
      //Update properties
  }
  private synchronized void syncUpdateIn() {
      while (readCount > 0) {
          try {
              wait();
          } catch (Exception e) {
          }
      }
  }
  private synchronized void syncReadIn() {
      readCount++;
  }
  private synchronized void syncReadOut() {
      readCount--;
      notifyAll();
  }
  public Vector getProperties() {
      syncReadIn();
      //Process data
      syncReadOut();
      return properties;
  }
}

 

2,采用"影子实例"的办法

具体说,就是在更新属性时,直接生成另一个单例对象实例,这个新生成的单例对象实例将从数据库或文件中读取最新的配置信息;然后将这些配置信息直接赋值给旧单例对象的属性。如下面代码所示。

public class GlobalConfig {
  private static GlobalConfig instance = null;
  private Vector properties = null;
  private GlobalConfig() {
    //Load configuration information from DB or file
    //Set values for properties
  }
  private static synchronized void syncInit() {
    if (instance = null) {
      instance = new GlobalConfig();
    }
  }
  public static GlobalConfig getInstance() {
    if (instance = null) {
      syncInit();
    }
    return instance;
  }
  public Vector getProperties() {
    return properties;
  }
  public void updateProperties() {
    //Load updated configuration information by new a GlobalConfig object
    GlobalConfig shadow = new GlobalConfig();
    properties = shadow.getProperties();
  }
}

注意:在更新方法中,通过生成新的GlobalConfig的实例,从文件或数据库中得到最新配置信息,并存放到properties属性中。

上面两个方法比较起来,第二个方法更好,首先,编程更简单;其次,没有那么多的同步操作,对性能的影响也不大。

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值