前言
一直在学习Android, 但是都总觉得是在造轮子, 所以还是得把java学深刻, 不然很多线程不安全的东西就会出现.
单例模式
饿汉式单例式
所谓饿汉就是在程序启动或单例模式类被加载的时候, 单例模式实例就已经被创建
public class Singleton{ private static Singleton singleton = new Singleton(); private Singleton(){} public static Singleton getInstance(){ return singleton; } }
缺点: 不管是否需要都会创建这个对象实例, 但是我们总希望能够按需求做事.
懒汉式(线程不安全)
懒汉: 当程序第一次访问单例模式实例时才进行创建.
public class Singleton{ private static Singleton singleton; private Singleton(){} public static Singleton getInstance(){ if(singleton==null){ singleton = new Singleton(); } return singleton; } }
缺点: 在多线程中不能正常工作,详情请点击: 解决单例设计模式中懒汉式线程安全问题
懒汉(线程安全)
很明显下面代码中加了一个关键字 synchronized 锁
public class Singleton{ private static Singleton singleton; private Singleton(){} public static synchronized Singleton getInstance(){ if(singleton==null){ singleton = new Singleton(); } return singleton; } }
缺点: 虽然能在多线程正常工作, 效率太低.
静态内部类
当Singleton类被加载的时候, singleton并没有被初始化, 因为SingletonHolder类没有被主动使用,只有调用getInstance方法时才会显示加载SingletonHolder类
public class Singleton{ private static class SingletonHolder{ private static Singleton singleton = new Singleton(); } private Singleton(){} public static Singleton getInstance(){ return SingletonHolder.singleton; } }
注: 以上的实现方法都有两个共同缺点;都需要额外的工作来实现序列化; 可以使用反射强行调用私有构造器(可以让构造器在创建第二的实例时抛异常).
枚举
这种写法很特殊, 在实际工作中也很少见, 在Android平台是不被推荐的.
但是线程安全和防止反射强行调用构造器, 还提供了自动序列化机制.public enum Singleton{ INSTANCE; public void whateverMethod(){ } }
双重检验锁
在jdk1.5之后就有了双重校验锁, 这是我觉得最好的一个方法.
public class Singleton{ private static Singleton singleton; private Singleton(){} public static Singleton getInstance(){ if(singleton==null){ synchronized(Singleton.class){ if(singleton==null){ singleton = new Singleton(); } } } return singleton; } }
牢记
不管采用什么方式实现, 都要牢记单例的三大要点:
线程安全
延迟加载
序列化与反序列化安全