废话不多说,首先来看单例设计模式。

一、 单例设计模式(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 }

其实改进方法还有很多,比如:静态持有者模式、枚举方法实现单例模式等。

特别说明:线程安全问题?

全局变量及静态变量引起的。(摘自百度百科)