设计模式——单例模式(Java)——考虑多线程环境下的线程安全问题
一:单例模式概念
单例模式是一种常用的软件设计模式。在它的核心结构中只包含一个被称为单例的特殊类。通过单例模式可以保证系统中一个类只有一个实例
二:单例模式的实现方式
特别注意,在多线程环境下,需要对获取对象实例的方法加对象锁(synchronized)
方式一:(懒汉式)程序执行过程中需要这个类的对象,再实例化这个类的对象
步骤:
1.定义静态私有对象
2.构造方法私有化保证在类的外部无法实例化该类的对象
3.定义对外开放的静态方法在调用方法时判断对象是否为空,为空再创建对象返回
public class Singleton{
//1.定义静态私有对象
priavate static Singleton singleton;
//2.构造方法私有化,保证在类的外部无法实例化该类的对象
private Singleton(){
}
//3.定义对外开放的静态方法在调用方法是判断对象是否为空,为空再创建对象返回
public static synchronized Singleton getSingletonInstance(){
if(singleton==null){
singleton=new Singleton();
}
return singleton;
}
}
方式二:(饿汉式)类加载的时候就实例化该类的对象
步骤:
1.定义静态私有对象,并实例化
2.构造方法私有化保证在类的外部无法实例化该类的对象
3.定义对外开放的静态方法
public class Singleton{
//1.定义静态私有对象,并实例化
priavate static Singleton singleton=new Singleton();
//2.构造方法私有化,保证在类的外部无法实例化该类的对象
private Singleton(){
}
//3.定义对外开放的静态方法
public static synchronized Singleton getSingletonInstance(){
return singleton;
}
}
三:在多线程情况下,单例对象的同步问题
1.单例对象的初始化
1.1问题引入:
在多线程情况下,如果第一个线程发现对象为空,准备创建;这时第二个线程同时也发现对象为空,也会创建。这样就会造成在一个JVM中有多个单例类型的实例。
1.2问题解决:(对象的创建加同步锁sychronized)
1 //单例对象的初始化同步 2 public class GlobalConfig { 3 private static GlobalConfig instance = null; 4 private Vector properties = null; 5 private GlobalConfig() { 6 //Load configuration information from DB or file 7 //Set values for properties 8 } 9 private static synchronized void syncInit() { 10 if (instance == null) { 11 instance = new GlobalConfig(); 12 } 13 } 14 public static GlobalConfig getInstance() { 15 if (instance == null) { 16 syncInit(); 17 } 18 return instance; 19 } 20 public Vector getProperties() { 21 return properties; 22 } 23 }
这种处理方式虽然引入了同步代码,但是因为这段同步代码只会在最开始的时候执行一次或多次,所以对整个系统的性能不会有影响。
2.单例对象的属性更新
2.1问题引入:
当一个线程更新单例对象的属性时,如果有另一个线程正在读取,这样就会造成属性值的不一致问题
2.2问题解决:
参照读者/写者的处理方式,设置一个读计数器,每次读取配置信息前,将计数器加1,读完后将计数器减1.只有在读计数器为0时,才能更新数据,同时要阻塞所有读属性的调用。
public class GlobalConfig { 2 private static GlobalConfig instance = null; 3 private Vector properties = null; 4 private GlobalConfig() { 5 //Load configuration information from DB or file 6 //Set values for properties 7 } 8 private static synchronized void syncInit() { 9 if (instance = null) { 10 instance = new GlobalConfig(); 11 } 12 } 13 public static GlobalConfig getInstance() { 14 if (instance = null) { 15 syncInit(); 16 } 17 return instance; 18 } 19 public Vector getProperties() { 20 return properties; 21 } 22 public void updateProperties() { 23 //Load updated configuration information by new a GlobalConfig object 24 GlobalConfig shadow = new GlobalConfig(); 25 properties = shadow.getProperties(); 26 } 27 }
参考资料:
1.
Java单例模式深入详解:
http://www.cnblogs.com/hxsyl/archive/2013/03/19/2969489.html
2.
单例模式多线程问题:
http://zhidao.baidu.com/question/2116683855745036107.html
时间: 2024-10-10 10:10:03