重新理解单例模式
来源:互联网 发布:linux编写c语言 编辑:程序博客网 时间:2024/05/16 06:25
重新理解单例模式
单例模式是设计模式中应用最广的一种设计模式,其核心就是将构造函数私有化,通过静态方法获取一个唯一的实例,当然在这个过程中要保证线程更是安全的。
常用的单例模式有
懒汉模式
public class Vip { private static Vip mVip=null; private void Vip() {} public static synchronized Vip getVip(){ if(mVip==null){ mVip=new Vip(); } return mVip; }}
饿汉模式
public class Boss { private static final Boss mBoss=new Boss(); private void Boss(){ } public static Boss getBoss(){ return mBoss; }}
其两种模式的区别就是饿汉模式一个是程序在java虚拟机创建就进行初始化,懒汉模式在首次调用才进行初始化。但是,懒汉模式每次调用都要调用synchronized关键字进行线程同步,造成了不必要的内存开销,反映较慢不推荐使用。从而演变出了DLC (double check lock )从字面意思来看就是双次检查锁定,通过2次空判断来避免懒汉模式中synchronized关键字每次都要进行同步问题。
DLC
public class Vip { private static Vip mVip=null; private Vip(){} public static Vip getInstance(){ if(mVip==null){ synchronized (Vip.class) { if(mVip==null){ mVip =new Vip(); } } } return mVip; }}
但是DLC模式有一个问题,上面的代码可以看作在内存进行了如下几部操作
1.分配实例内存
2.调用构造函数,初始化
3.将synchronized对象指向分配的内存空间(这时mVip不为空)
但是,由于java编译器可以乱序执行,1-2-3的顺序当然没问题,但是如果先1-3然后切换到了B线程,由于执行了3 mVip已经不为空却没有初始化,这时候就导致了DLC失效。当然也就解决方法就是加上volatile关键字。变为 private static volatile Vip mVip=null;
。DLC可以满足大多数场景的要求,但是由于volatile关键字是java 5.0才出现的所以,DLC出现了驱动力不足,而且这也并不是一种高效的优化措施。
静态内部类单例模式
public class Singleton { private void Singleton() { } public static Singleton getSingleton() { return SingletonHolder.mSingleton; } private static class SingletonHolder { private static final Singleton mSingleton = new Singleton(); }}
第一次加载Singleton并不会初始化mSingleton只有在第一次调用getSingleton才会导致mSingleton被初始化,因此,第一次调用getSingleton会导致虚拟机加载SingletonHolder类,这种方式不仅可以保证线程安全,也可以保证对象唯一性,同时从代码层面也更加简介,是推荐的单例实现模式。
枚举单例
public enum SingletonEnum { INSTANCE; public void doSomething(){// Log.e("test","test") }}
因为枚举在java中和普通的类一样不仅可以有字段,还可以有方法,最重要的是枚举默认创建的线程是安全的,且在任何情况下它都是一个单例。但是,上面的几个案例在一种情况下会导致单例重新创建,那就是序列化,在反序列化的时候会导致对象重新创建的情况。如果想杜绝单例模式在反序列化中重新创建的问题就要实现 readResole方法。
private Object readResolve() throws ObjectStreamException{
return mSingleton;
}
容器单例模式
public class SingletonManager { private static Map<String, Object> objMap = new HashMap<String, Object>(); private SingletonManager() { } public static void registerService(String key, Object obj) { if (!objMap.containsKey(key)) { objMap.put(key, obj); } } public static Object getService(String key) { return objMap.get(key); }}
利用Map的特性可以将多个单例放到一个容器中管理,根据key得到对应的对象
单例在安卓源码中的使用
嗨呀!我也不知道后面怎么写。很乱等我整理出来单独开一章。
- 重新理解单例模式
- 重新理解单态模式
- 阅读ISE源码过程中重新对单例模式的理解
- 单例模式理解
- 理解单例模式
- MVC模式 重新理解
- 单例模式浅理解
- JAVA单例模式理解
- 单例模式深入理解
- 单例模式 自我理解
- JAVA理解单例模式
- 单例模式的理解
- 单例模式的理解
- 简单理解单例模式
- 彻底理解单例模式
- 深入理解单例模式
- 深入理解单例模式
- 单例模式的理解
- OnClose()和 OnDestroy()
- 【安全牛学习笔记】WEBSHELL
- OpenCV-将图像转化为灰度图,然后边缘检测
- c++ inline variable 内联变量 c++17
- linux 网络编程:使用两线程实现socket同时收发数据
- 重新理解单例模式
- 胸腔阻抗成像中的常用术语
- 迅为Exynos4412开发板例程及注释——注册字符类设备
- 入口文件模块绑定
- ubuntu16.04安装+cuda8.0+cudnn5.1+MXNET gpu版本安装+tensorflow gpu版本安装+chainerGPU版本安装
- leetcode-496. Next Greater Element I
- shell 创建多个指定大小的文件,循环删除指定大小文件
- 布局相关的细节和屏幕适配
- 访问外部接口时报错2017-09-30 15:47:21.791 ERROR 23312 --- [apr-8092-exec-5] o.s.boot.web.support.ErrorPageFil