软件培训网

欢迎访问软件培训网!招生咨询电话与微信:15225191462(周老师)
软件培训网,专业解决学IT疑难杂症!

首页 > 软件测试/ 正文

Java单例对象同步问题探讨

2012-09-14 19:01:47

  单例对象(Singleton)是一种常用的设计模式。在Java应用中,单例对象能保证在一个JVM中,该对象只有一个实例存在。正是由于这个特点,单例对象通常作为程序中的存放配置信息的载体,因为它能保证其他对象读到一致的信息。例如在某个服务器程序中,该服务器的配置信息可能存放在数据库或文件中,这些配置数据由某个单例对象统一读取,服务进程中的其他对象如果要获取这些配置信息,只需访问该单例对象即可。这种方式极大地简化了在复杂环境下,尤其是多线程环境下的配置管理,但是随着应用场景的不同,也可能带来一些同步问题。GzY软件IT培训网-河南郑州IT培训

  问题描述GzY软件IT培训网-河南郑州IT培训

  在多线程环境下,单例对象的同步问题主要体现在两个方面,单例对象的初始化和单例对象的属性更新。GzY软件IT培训网-河南郑州IT培训

  本文描述的方法有如下假设:GzY软件IT培训网-河南郑州IT培训

  单例对象的属性(或成员变量)的获取,是通过单例对象的初始化实现的。也就是说,在单例对象初始化时,会从文件或数据库中读取最新的配置信息。GzY软件IT培训网-河南郑州IT培训

  其他对象不能直接改变单例对象的属性,单例对象属性的变化来源于配置文件或配置数据库数据的变化。GzY软件IT培训网-河南郑州IT培训

  1.1 单例对象的初始化GzY软件IT培训网-河南郑州IT培训

  首先,讨论一下单例对象的初始化同步。单例模式的通常处理方式是,在对象中有一个静态成员变量,其类型就是单例类型本身;如果该变量为null,则创建该单例类型的对象,并将该变量指向这个对象;如果该变量不为null,则直接使用该变量。GzY软件IT培训网-河南郑州IT培训

  其过程如下面代码所示:GzY软件IT培训网-河南郑州IT培训

  1 public class GlobalConfig {GzY软件IT培训网-河南郑州IT培训

  2 private static GlobalConfig instance = null;GzY软件IT培训网-河南郑州IT培训

  3 private Vector properties = null;GzY软件IT培训网-河南郑州IT培训

  4 private GlobalConfig() {GzY软件IT培训网-河南郑州IT培训

  5 //Load configuration information from DB or fileGzY软件IT培训网-河南郑州IT培训

  6 //Set values for propertiesGzY软件IT培训网-河南郑州IT培训

  7 }GzY软件IT培训网-河南郑州IT培训

  8 public static GlobalConfig getInstance() {GzY软件IT培训网-河南郑州IT培训

  9 if (instance == null) {GzY软件IT培训网-河南郑州IT培训

  10 instance = new GlobalConfig();GzY软件IT培训网-河南郑州IT培训

  11 }GzY软件IT培训网-河南郑州IT培训

  12 return instance;GzY软件IT培训网-河南郑州IT培训

  13 }GzY软件IT培训网-河南郑州IT培训

  14 public Vector getProperties() {GzY软件IT培训网-河南郑州IT培训

  15 return properties;GzY软件IT培训网-河南郑州IT培训

  16 }GzY软件IT培训网-河南郑州IT培训

  17 }GzY软件IT培训网-河南郑州IT培训

  18GzY软件IT培训网-河南郑州IT培训

  这种处理方式在单线程的模式下可以很好的运行;但是在多线程模式下,可能产生问题。如果第一个线程发现成员变量为null,准备创建对象;这是第二个线程同时也发现成员变量为null,也会创建新对象。这就会造成在一个JVM中有多个单例类型的实例。如果这个单例类型的成员变量在运行过程中变化,会造成多个单例类型实例的不一致,产生一些很奇怪的现象。例如,某服务进程通过检查单例对象的某个属性来停止多个线程服务,如果存在多个单例对象的实例,就会造成部分线程服务停止,部分线程服务不能停止的情况。GzY软件IT培训网-河南郑州IT培训

  1.2 单例对象的属性更新GzY软件IT培训网-河南郑州IT培训

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

  解决方法GzY软件IT培训网-河南郑州IT培训

  2.1 单例对象的初始化同步GzY软件IT培训网-河南郑州IT培训

  对于初始化的同步,可以通过如下代码所采用的方式解决。GzY软件IT培训网-河南郑州IT培训

  1 public class GlobalConfig {GzY软件IT培训网-河南郑州IT培训

  2 private static GlobalConfig instance = null;GzY软件IT培训网-河南郑州IT培训

  3 private Vector properties = null;GzY软件IT培训网-河南郑州IT培训

  4 private GlobalConfig() {GzY软件IT培训网-河南郑州IT培训

  5 //Load configuration information from DB or fileGzY软件IT培训网-河南郑州IT培训

  6 //Set values for propertiesGzY软件IT培训网-河南郑州IT培训

  7 }GzY软件IT培训网-河南郑州IT培训

  8 private static synchronized void syncInit() {GzY软件IT培训网-河南郑州IT培训

  9 if (instance == null) {GzY软件IT培训网-河南郑州IT培训

  10 instance = new GlobalConfig();GzY软件IT培训网-河南郑州IT培训

  11 }GzY软件IT培训网-河南郑州IT培训

  12 }GzY软件IT培训网-河南郑州IT培训

  13 public static GlobalConfig getInstance() {GzY软件IT培训网-河南郑州IT培训

  14 if (instance == null) {GzY软件IT培训网-河南郑州IT培训

  15 syncInit();GzY软件IT培训网-河南郑州IT培训

  16 }GzY软件IT培训网-河南郑州IT培训

  17 return instance;GzY软件IT培训网-河南郑州IT培训

  18 }GzY软件IT培训网-河南郑州IT培训

  19 public Vector getProperties() {GzY软件IT培训网-河南郑州IT培训

  20 return properties;GzY软件IT培训网-河南郑州IT培训

  21 }GzY软件IT培训网-河南郑州IT培训

  22 }GzY软件IT培训网-河南郑州IT培训

  23GzY软件IT培训网-河南郑州IT培训

  这种处理方式虽然引入了同步代码,但是因为这段同步代码只会在最开始的时候执行一次或多次,所以对整个系统的性能不会有影响。GzY软件IT培训网-河南郑州IT培训

  2.2 单例对象的属性更新同步GzY软件IT培训网-河南郑州IT培训

  为了解决第2个问题,有两种方法:GzY软件IT培训网-河南郑州IT培训

  1,参照读者/写者的处理方式GzY软件IT培训网-河南郑州IT培训

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

  1 public class GlobalConfig {GzY软件IT培训网-河南郑州IT培训

  2 private static GlobalConfig instance;GzY软件IT培训网-河南郑州IT培训

  3 private Vector properties = null;GzY软件IT培训网-河南郑州IT培训

  4 private boolean isUpdating = false;GzY软件IT培训网-河南郑州IT培训

  5 private int readCount = 0;GzY软件IT培训网-河南郑州IT培训

  6 private GlobalConfig() {GzY软件IT培训网-河南郑州IT培训

  7 //Load configuration information from DB or fileGzY软件IT培训网-河南郑州IT培训

  8 //Set values for propertiesGzY软件IT培训网-河南郑州IT培训

  9 }GzY软件IT培训网-河南郑州IT培训

  10 private static synchronized void syncInit() {GzY软件IT培训网-河南郑州IT培训

  11 if (instance == null) {GzY软件IT培训网-河南郑州IT培训

  12 instance = new GlobalConfig();GzY软件IT培训网-河南郑州IT培训

  13 }GzY软件IT培训网-河南郑州IT培训

  14 }GzY软件IT培训网-河南郑州IT培训

  15 public static GlobalConfig getInstance() {GzY软件IT培训网-河南郑州IT培训

  16 if (instance==null) {GzY软件IT培训网-河南郑州IT培训

  17 syncInit();GzY软件IT培训网-河南郑州IT培训

  18 }GzY软件IT培训网-河南郑州IT培训

  19 return instance;GzY软件IT培训网-河南郑州IT培训

  20 }GzY软件IT培训网-河南郑州IT培训

  21 public synchronized void update(String p_data) {GzY软件IT培训网-河南郑州IT培训

  22 syncUpdateIn();GzY软件IT培训网-河南郑州IT培训

  23 //Update propertiesGzY软件IT培训网-河南郑州IT培训

  24 }GzY软件IT培训网-河南郑州IT培训

  25 private synchronized void syncUpdateIn() {GzY软件IT培训网-河南郑州IT培训

  26 while (readCount > 0) {GzY软件IT培训网-河南郑州IT培训

  27 try {GzY软件IT培训网-河南郑州IT培训

  28 wait();GzY软件IT培训网-河南郑州IT培训

  29 } catch (Exception e) {GzY软件IT培训网-河南郑州IT培训

  30 }GzY软件IT培训网-河南郑州IT培训

  31 }GzY软件IT培训网-河南郑州IT培训

  32 }GzY软件IT培训网-河南郑州IT培训

  33 private synchronized void syncReadIn() {GzY软件IT培训网-河南郑州IT培训

  34 readCount++;GzY软件IT培训网-河南郑州IT培训

  35 }GzY软件IT培训网-河南郑州IT培训

  36 private synchronized void syncReadOut() {GzY软件IT培训网-河南郑州IT培训

  37 readCount--;GzY软件IT培训网-河南郑州IT培训

  38 notifyAll();GzY软件IT培训网-河南郑州IT培训

  39 }GzY软件IT培训网-河南郑州IT培训

  40 public Vector getProperties() {GzY软件IT培训网-河南郑州IT培训

  41 syncReadIn();GzY软件IT培训网-河南郑州IT培训

  42 //Process dataGzY软件IT培训网-河南郑州IT培训

  43 syncReadOut();GzY软件IT培训网-河南郑州IT培训

  44 return properties;GzY软件IT培训网-河南郑州IT培训

  45 }GzY软件IT培训网-河南郑州IT培训

  46 }GzY软件IT培训网-河南郑州IT培训

  47GzY软件IT培训网-河南郑州IT培训

  2,采用"影子实例"的办法GzY软件IT培训网-河南郑州IT培训

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

  1 public class GlobalConfig {GzY软件IT培训网-河南郑州IT培训

  2 private static GlobalConfig instance = null;GzY软件IT培训网-河南郑州IT培训

  3 private Vector properties = null;GzY软件IT培训网-河南郑州IT培训

  4 private GlobalConfig() {GzY软件IT培训网-河南郑州IT培训

  5 //Load configuration information from DB or fileGzY软件IT培训网-河南郑州IT培训

  6 //Set values for propertiesGzY软件IT培训网-河南郑州IT培训

  7 }GzY软件IT培训网-河南郑州IT培训

  8 private static synchronized void syncInit() {GzY软件IT培训网-河南郑州IT培训

  9 if (instance = null) {GzY软件IT培训网-河南郑州IT培训

  10 instance = new GlobalConfig();GzY软件IT培训网-河南郑州IT培训

  11 }GzY软件IT培训网-河南郑州IT培训

  12 }GzY软件IT培训网-河南郑州IT培训

  13 public static GlobalConfig getInstance() {GzY软件IT培训网-河南郑州IT培训

  14 if (instance = null) {GzY软件IT培训网-河南郑州IT培训

  15 syncInit();GzY软件IT培训网-河南郑州IT培训

  16 }GzY软件IT培训网-河南郑州IT培训

  17 return instance;GzY软件IT培训网-河南郑州IT培训

  18 }GzY软件IT培训网-河南郑州IT培训

  19 public Vector getProperties() {GzY软件IT培训网-河南郑州IT培训

  20 return properties;GzY软件IT培训网-河南郑州IT培训

  21 }GzY软件IT培训网-河南郑州IT培训

  22 public void updateProperties() {GzY软件IT培训网-河南郑州IT培训

  23 //Load updated configuration information by new a GlobalConfig objectGzY软件IT培训网-河南郑州IT培训

  24 GlobalConfig shadow = new GlobalConfig();GzY软件IT培训网-河南郑州IT培训

  25 properties = shadow.getProperties();GzY软件IT培训网-河南郑州IT培训

  26 }GzY软件IT培训网-河南郑州IT培训

  27 }GzY软件IT培训网-河南郑州IT培训

  28GzY软件IT培训网-河南郑州IT培训

  注意:在更新方法中,通过生成新的GlobalConfig的实例,从文件或数据库中得到最新配置信息,并存放到properties属性中。GzY软件IT培训网-河南郑州IT培训

  上面两个方法比较起来,第二个方法更好,首先,编程更简单;其次,没有那么多的同步操作,对性能的影响也不大。GzY软件IT培训网-河南郑州IT培训


Tags:安卓系统入门培训,安卓培训凤凰教育,安卓开发培训,北大青鸟安卓培训,安卓系统培训教材,java

搜索
软件培训学校哪家好,就来软件培训网咨询
软件培训学校哪家好,就来软件培训网咨询
热门标签
软件培训学校哪家好,就来软件培训网咨询
软件培训学校哪家好,就来软件培训网咨询
软件培训学校哪家好,就来软件培训网咨询
  • QQ交谈