废话不多说,首先来看单例设计模式。
一、 单例设计模式(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 }
其实改进方法还有很多,比如:静态持有者模式、枚举方法实现单例模式等。
特别说明:线程安全问题?
全局变量及静态变量引起的。(摘自百度百科)