一、懒汉模式
package com.pengli.designmode.singleton; public class Singleton1 { // 私有静态变量 // 需要 用volatile修饰 private static volatile Singleton1 singleton = null; // 私有构造函数,不能实例化 private Singleton1() { } // 静态工厂方法 public static synchronized Singleton1 getInstance() { if (singleton == null) { synchronized (Singleton1.class) { if (singleton == null) { singleton = new Singleton1(); } } } return singleton; } }
1、double-check可实现并非每次都使用synchronized进行锁定,提高性能;
2、synchronized能够实现第一次实例化时的线程安全;
3、为什么还要使用volatile呢?
答案:
不加的情况下,假设两个线程,线程A正在执行instance = new Instance()的操作,而线程B开始执行if(instance==null)的判断,当不存在volatile的时候,因为 new Instance()是一个非原子操作,可能发生无序写入,构造函数可能在整个对象构造完成前执行完毕,线程B可能会看到一个不完整的instance对象,因为java的某些实现会在内存中开辟一片存储对象的区域后直接返回内存的引用,所以线程B判断不为null,而这时候实际上,instance的构造函数还没有执行,从而线程b得到不完整的对象。
在 Instance 的构造函数执行之前,会在内存中开辟一片存储对象的区域后直接返回内存的引用,赋值给变量 instance,instance也就可能成为非 null 的,即赋值语句在对象实例化之前调用,此时别的线程得到的是一个还会初始化的对象,这样会导致系统崩溃线程B可能会看到一个不完整的instance对象,因为java的某些实现,所以线程B判断不为null。从而得到不完整的对象。
在 Instance 的构造函数执行之前,会在内存中开辟一片存储对象的区域后直接返回内存的引用,赋值给变量 instance,instance也就可能成为非 null 的,即赋值语句在对象实例化之前调用,此时别的线程得到的是一个还会初始化的对象,这样会导致系统崩溃线程B可能会看到一个不完整的instance对象,因为java的某些实现,所以线程B判断不为null。从而得到不完整的对象。
package com.pengli.designmode.singleton; public class Singleton2 { private static class LazyHolder { private static final Singleton2 INSTANCE = new Singleton2(); } private Singleton2() { } public static final Singleton2 getInstance() { return LazyHolder.INSTANCE; } }
二、饿汉模式
package com.pengli.designmode.singleton; //饿汉式单例类.在类初始化时,已经自行实例化 public class Singleton3 { private Singleton3() {} private static final Singleton3 single = new Singleton3(); //静态工厂方法 public static Singleton3 getInstance() { return single; } }
参考:
http://blog.csdn.net/jason0539/article/details/23297037/
http://www.iteye.com/topic/652440