单例模式,1)静态变量来记录Singlegton类的唯一实例。2)私有构造方法。3)getInstance方法实例化对象,并返回这个实例。

1、先看看经典的单例模式写法 

 1 public class Singleton {
 2     private static Singleton instance;
 3     private Singleton(){
 4         
 5     }
 6     public static Singleton getInstance(){
 7         if (instance==null) {
 8             instance = new Singleton();
 9         }
10         return instance;
11     }
12 }

看起来貌似没什么问题,其实不然,实际应用中,显然多线程同时访问时getInstance方法时,是有可能创建不同的实例的。

2、处理多线程的单例模式写法

 1 public class Singleton {
 2     private static Singleton instance;
 3     private Singleton(){
 4         
 5     }
 6     public static synchronized Singleton getInstance(){
 7         if (instance==null) {
 8             instance = new Singleton();
 9         }
10         return instance;
11     }
12 }

通过增加synchronized关键字到getInstance方法中,可以解决多线程引发的创建不同实例的问题。但是同步会降低性能,这不是另一个问题么?

3、使用“急切”创建实例,而不是延迟实例化的做法

1 public class Singleton {
2     private static Singleton instance = new Singleton();
3     private Singleton(){
4         
5     }
6     public static  Singleton getInstance(){
7         return instance;
8     }
9 }

这种做法,我们依赖JVM在加载这个类时马上创建唯一的实例。JVM保证在任何线程访问instance之前,一定先创建此实例。但不推荐。建议“延迟实例化”(lazy instantiaze)

4、用“双重检查加锁”,在getInstace中减少使用同步(推荐)

 1 public class Singleton {
 2     // volatile关键字确保:当instance变量被初始化Singleton实例时,
 3     //多个线程能正确处理instance变量
 4     private volatile static Singleton instance ;
 5     private Singleton(){
 6         
 7     }
 8     public static  Singleton getInstance(){
 9         if (instance==null) {
10             synchronized (Singleton.class) {
11                 if (instance==null) {
12                     instance = new Singleton();
13                 }
14             }
15         }
16         return instance;
17     }
18 }

注意:关于双重加锁不适用 1.4及更早版本

如果性能是你关心的重点,那么这个做法可以帮你大大地减少getInstance的时间消耗。