Java 设计模式(单例设计模式)
废话不多说,首先来看单例设计模式。
一、 单例设计模式(Singleton)
从字面意思来看,单例--一个例子,设计--用于实现某种东西(功能)的想法实现,模式--一种固定的“套路”。那java中的单例设计模式到底是什么概念呢?单例设计模式是保证一个类中仅有一个实例,并提供一个访问它的全局控制点。
单例模式的实现有两种方式:a. 饿汉单例模式;b. 懒汉单例模式
a. 饿汉单例模式
1 public class HungryModel { 2 //私有化构造函数 3 private HungryModel(){} 4 //声明本类的引用类型变量,并且使用该变量指向本类对象 5 private static HungryModel m = new HungryModel(); 6 //提供一个公共的静态的方法获取本类对象 7 public static HungryModel getInstance(){ 8 return m; 9 } 10 }
从代码中可以看出,不管我们用不用这个实例,它早已创建(在类被加载时就已创建),这很明显就是一种"浪费",为此,懒汉单例模式诞生了。
b. 懒汉单例模式
1 public class LazyModel{ 2 //私有化构造函数 3 private LazyModel(){} 4 //声明本类的引用类型变量 5 private static LazyModel m; 6 //提供一个公共的静态的方法获取本类对象 7 public static LazyModel getInstance(){ 8 //先判断后创建 9 if(m == null){ 10 m = new LazyModel(); 11 } 12 return m; 13 } 14 }
懒汉单例模式的缺点:存在线程安全问题,在多线程环境下会出现多个实例的情况。
改进方法1:使用synchronized关键字修饰方法(也可以使用synchronized同步代码块来实现),使其同步,缺点是:效率低。
1 public class HungryModel{ 2 private HungryModel(){} 3 private static HungryModel m; 4 public static synchronized HungryModel getInstance(){ 5 if(m == null){ 6 m = new HungryModel(); 7 } 8 return m; 9 } 10 }
改进方法2:使用双检查锁机制(DCL--double check locking),顾名思义就是检查两次,一次不加锁一次加锁。使用此方法时,要使用volatile修饰引用变量。
1 public class HungryModel{ 2 //私有化构造函数 3 private HungryModel(){} 4 //用volatile修饰本类的引用类型变量 5 private volatile static HungryModel m; 6 //提供一个公共的静态的方法获取本类对象 7 public static HungryModel getInstance(){ 8 if(m == null){ 9 synchronized (HungryModel.class){ 10 if(m == null){ 11 m = new HungryModel(); 12 } 13 } 14 } 15 return m; 16 } 17 }
其实改进方法还有很多,比如:静态持有者模式、枚举方法实现单例模式等。
特别说明:线程安全问题?
线程安全就是多线程访问时,采用了加锁机制,当一个线程访问该类的某个数据时,进行保护,其他线程不能进行访问直到该线程读取完,其他线程才可使用。不会出现数据不一致或者数据污染。 线程不安全就是不提供数据访问保护,有可能出现多个线程先后更改数据造成所得到的数据是脏数据。线程安全问题都是由全局变量及静态变量引起的。(摘自百度百科)