单例模式用得应该很频繁啊,而且也比较简单下面介绍几种线程安全的且我觉得还比较不错的方式:
1.恶汉式:
避免了多线程的同步问题,不过instance在类装载时就实例化,虽然导致类装载的原因有很多种,在单例模式中大多数都是调用getInstance方法。
public class Singleton { private static Singleton instance = new Singleton(); public static Singleton getInstance() { return instance ; } }2.懒汉式:
懒汉式本来是属于线程不安全的(99%情况下不需要同步这里做双重判断,因为并发量大的时候如果有多个地方同时调用这个实例的话 会出现并行阻塞 所以 加上同步块),但是加上同步块以后虽然效率上有所降低 但是至少是属于线程安全的
public class Singleton02 { private static Singleton02 instance; public static Singleton02 getInstance() { if (instance == null) { synchronized (Singleton02.class) { if (instance == null) { instance = new Singleton02(); } } } return instance; } }
3.静态内部类的形式
这是一个特殊的方式,使用一个持有类,不在初始化的时候加载,它跟前面两种方式不同的是(很细微的差别):前面的只要Singleton类被装载了,那么instance就会被实例化,而这种方式是Singleton类被装载了,instance不一定被初始化。因为Singleton类没有被主动使用,只有显示通过调用getInstance方法时,才会显示装载Singleton类,从而实例化instance,想象一下,如果实例化instance很消耗资源,我想让他延迟加载,另外一方面,我不希望在Singleton类加载时就实例化,因为我不能确保Singleton类还可能在其他的地方被主动使用从而被加载,那么这个时候实例化instance显然是不合适的。这个时候,这种方式就能很好的解决。
public class Singleton03 { private static final class InstanceHolder { private static Singleton03 INSTANCE = new Singleton03(); } public static Singleton03 getInstance() { return InstanceHolder.INSTANCE; } }4.枚举式:
它不仅能避免多线程同步问题,而且还能防止反序列化重新创建 新的对象
public enum Singleton4 { INSTANCE; public void wheverMethod(){ } }
5.双重校检锁式:
public class Singleton5 { private volatile static Singleton5 singleton; private Singleton6() { } public static Singleton5 getInstance() { if (singleton == null) { synchronized (Singleton.class) { if (singleton == null) { singleton = new Singleton6(); } } } return singleton; } }
单例模式应用的场景一般发现在以下条件下:
(1)资源共享的情况下,避免由于资源操作时导致的性能或损耗等。如上述中的日志文件,应用配置。
(2)控制资源的情况下,方便资源之间的互相通信。如线程池等。
(3)在Android当中 application对象就是一个全局的单例 一般可以在当中做一个全局的数据的初始化和保存工作,以及需要在项目当中保存一些数据都可以使用单例 ,使用单例也要慎重考虑 单例往往会带来性能上的资源消耗 并且单例的生命周期跟整个application 一样长的 在使用context时 要引用跟它生命周期一样长的applicationcontext 如果传入的是activity的context 由于单例的生命周期比actvity长 当acitvity销毁时 单例还持有该contextd 的引用 从而导致内存泄露。