饿汉式
提前new出来实例了,并不是在第一次调用get方法时才实例化,没有进行延迟加载
public class Singleton1 { private static Singleton1 instance = new Singleton1(); private Singleton1(){} public static Singleton1 getInstance(){ return instance; }}
懒汉式——非线程安全版本
多线程环境下无法保证单例效果,会多次执行 instance=new Singleton(),需要考虑到多线程
public class Singleton2 { private static Singleton2 instance; private Singleton2(){} public static Singleton2 getInstance(){ if(instance == null){ instance = new Singleton2(); } return instance; }}
懒汉式——同步代码块版
性能不高,同步范围太大,在实例化instacne后,获取实例仍然是同步的,效率太低,需要缩小同步的范围。
public class Singleton3 { private static Singleton3 instance; private Singleton3(){} public static synchronized Singleton3 getInstance(){ if(instance == null){ instance = new Singleton3(); } return instance; }}
懒汉式——同步方法一层check版
缩小同步范围,来提高性能,但是让然存在多次执行instance=new Singleton()的可能,由此引出double check
方法:
- 实例方法,锁住的是实例,public synchronized void method()
- 静态方法,锁住的是类,public static synchronized void method()
代码块:
- 实例对象,锁住的是实例对象,synchronized(this){}
- class对象,锁住的是类对象,synchronized(xxx.class){}
- 任意对象, 实例对象的Object,string ss; synchronized(ss){}
public class Singleton4 { private static Singleton4 instance; private Singleton4(){} public static Singleton4 getInstance(){ if(instance == null){ synchronized (instance){ instance = new Singleton4(); } } return instance; }}
懒汉式——double check版
避免的上面方式的明显缺点,但是java内存模型(jmm)并不限制处理器重排序,在执行instance=new Singleton();时,并不是原子语句。
public class Singleton5 { private static Singleton5 instance; private Singleton5(){} public static Singleton5 getInstance(){ if(instance == null){ synchronized (instance){ if(instance == null){ instance = new Singleton5(); } } } return instance; }}
终极版——volatile防指令重排避免多线程出错
创建一个对象,实际是包括了下面三大步骤:
- 为对象分配内存
- 初始化实例对象
- 把引用instance指向分配的内存空间
这个三个步骤并不能保证按序执行,处理器会进行指令重排序优化,存在这样的情况:优化重排后执行顺序为:1,3,2, 这样在线程1执行到3时,instance已经不为null了,线程2此时判断instance!=null,则直接返回instance引用,但现在实例对象还没有初始化完毕,此时线程2使用instance可能会造成程序崩溃。
public class Singleton6 { private static volatile Singleton6 instance; private Singleton6(){} public static Singleton6 getInstance(){ if(instance == null){ synchronized (instance){ if(instance == null){ instance = new Singleton6(); } } } return instance; }}
懒汉式——静态内部类
静态内部类实现的懒汉式.
静态部分依赖于类,而不是对象,因此会优先于对象加载。类执行的顺序:
- 静态属性、静态方法声明、静态块
- 动态属性、普通方法声明、普通代码块
- 构造方法
public class Singleton7 { private Singleton7(){} public static Singleton7 getInstance(){ return InstanceHolder.instance; } static class InstanceHolder{ private static Singleton7 instance = new Singleton7(); }}