安卓设计模式の单例模式
来源:互联网 发布:p2p平台数据分析指标 编辑:程序博客网 时间:2024/05/01 23:43
单例模式
是一种常用的软件设计模式。在它的核心结构中只包含一个被称为单例的特殊类。通过单例模式可以保证系统中,应用该模式的类一个类只有一个实例。即一个类只有一个对象实例
在安卓中,常用到的单例模式有六种:
饿汉\懒汉\懒汉线程安全\DCL\静态内部类\枚举;下面将一一作介绍
一、饿汉模式
code
public class HungrySingleton { private static final HungrySingleton mHungrySingleton = new HungrySingleton(); private HungrySingleton(){ System.out.println("Singleton is created"); } public static HungrySingleton getInstance(){ return mHungrySingleton; } public static void createString(){ System.out.println("createString is Singleton"); } public static void main(String[] args) { HungrySingleton.createString(); }}
输出为
Singleton is createdcreateString is Singleton
该模式的缺点比较明显,就是无法对instance实例做延时加载,加载时会有负载产生,例如构造中的代码会被执行~
对此模式进行优化,就是以下介绍的懒汉模式。
二、懒汉模式
code
public class LazySingleton { // 先不加载,等把类创建出来再利用getLazySingleton给instance赋值 private static LazySingleton instance; private LazySingleton(){ System.out.println("Singleton is created"); } public static LazySingleton getInstance(){ if (instance == null) {// 第一次调用时会被初始化 instance = new LazySingleton(); } return instance; } public static void createString(){ System.out.println("createString is Singleton"); } public static void main(String[] args) { LazySingleton.createString(); }}
输出为:
createString is Singleton
该模式就能减少单例创建过程中产生的负载,并且可以延时加载,什么时候需要加载,什么时候就调用getInstance即可
但是,该方法也有个弊端,就是在并发创建单例对象的过程中,这种单例的特点会全部丢失..
看下下面的代码示例:
public class MyThread extends Thread{ @Override public void run() { System.out.println(LazySingleton.getInstance().hashCode()); } public static void main(String[] args) { MyThread[] mts = new MyThread[10]; for (int i = 0; i < mts.length; i++) { mts[i] = new MyThread(); } for (int j = 0; j < mts.length; j++) { mts[j].start(); } }}
输出为:
Singleton is created7896426Singleton is created746194978964267461949746194974619497461949746194974619497461949
创建了不止一个对象,这就是说,单例模式失效了,这就是其不足之处:在多线程并发下这样的实现是无法保证实例的唯一的,对此我们又有了改进方法,就是下面的懒汉线程安全模式~
三、懒汉线程安全模式
code
//方式一:方法中声明synchronized关键字 public static synchronized LazySafetySingleton getInstance(){ if (instance == null) { //懒汉 instance = new LazySafetySingleton(); } return instance; } //方式二:同步代码块方式实现 public static LazySafetySingleton getInstance1(){ synchronized (LazySafetySingleton.class) { if (instance == null) { //懒汉 instance = new LazySafetySingleton(); } } return instance; }
虽然该模式相比懒汉模式是性能安全的,但是它有性能效率上的问题,如何解决此问题呢,没错就是DCL模式~
四、DCL(Double Check Lock双重检查锁)
code
public class DclSingleton { private static volatile DclSingleton instance = null; private DclSingleton(){ } public static DclSingleton getInstance(){ if (instance == null) { synchronized (DclSingleton.class) { if (instance ==null) { instance = new DclSingleton(); } } } return instance; }}
这个getInstance方法中对mSingleton进行了两次判空:第一次是为了避免不必要的同步锁;第二层是为了在null的时候创建实例。
不过这种模式会出现DCL失效:
在多线程下,假设A线程执行到mSingleton=new Singleton()的时候,CPU并不是一次性执行完这条语句的,因为这不是一个原子操作(指不会被线程调度机制打断的操作),mSingleton=new Singleton()大致做了三件事:
- 给Singleton的实例分配内存
- 调用Singleton的构造方法
- 将mSingleton指向分配的内存空间(这个时候mSingleton才不为空)
由于Java编译器允许处理器乱序执行,所以上面的第二步第三步的执行顺序没法得到保证。执行顺序可能是1-2-3也可能是1-3-2。
当A线程执行顺序是1-3-2的时候,如果执行到了1-3,第2步还没执行的时候,如果B线程判断mSingleton==null的时候就会的发哦FALSE的结果,从而返回一个错误的单例。
当然,改进方法如上面代码所做的,将变量用volatile修饰,这样可以禁止JVM的指令重排序优化,从而达到顺序执行的目的。
五、静态内部类
public class StaticInnerSingleton { private StaticInnerSingleton(){ } public static StaticInnerSingleton getInstance(){ return SingletonHolder.sinstance; } private static class SingletonHolder{ private static final StaticInnerSingleton sinstance = new StaticInnerSingleton(); }}
推荐面试啊什么的都用这种单例,它具有三个优点:
- 性能上的优越:不使用synchonized关键字,减少性能上的开销
- 可以实现延时加载:具备懒汉模式的优点
- 同时它也是性能(线程)安全的:它提供的static关键字(进行区块初始化数据,保证数据在内存中只读一份),final字段(定义后无法被修改),这是Java为我们提供的很实用的保证线程安全的同步控制。
六、枚举
public enum EnumSingleton { //定义一个枚举的元素,它就是EnumSingleton的一个实例 INSTANCE; public void otherMethods() { System.out.println("Something"); } public static void main(String[] args) { EnumSingleton instance = EnumSingleton.INSTANCE; instance.otherMethods(); }}
简简单单的一点代码就实现了一个线程安全,lazy loading的单例,具体可以看看枚举的用法。
总结
大体概括一下,推荐用静态内部类或者枚举的方法实现单例模式,其优点显而易见,代码也不难理解,但也要知道其他几种单例模式的特点以及需要改善的地方,这样的话算是理解了单例的几种模式。接下来是其他设计模式的讲解。
- 安卓设计模式の单例模式
- 安卓设计模式(二)单例模式
- 安卓设计模式_单例模式
- 安卓设计模式,工厂模式/单例模式/观察者模式/代理模式/
- 安卓 单例设计模式 查看方法
- 安卓中的两种设计模式:单例模式,观察者模式
- 安卓设计模式のBuilder模式
- 安卓设计模式のAdapter模式
- 安卓设计模式の组合模式
- 安卓设计模式の策略模式
- 安卓设计模式の外观模式
- 安卓设计模式の代理模式
- 安卓设计模式の观察者模式
- 最常用的设计模式之单例模式---安卓数据库为例
- Android 最常用的设计模式一 安卓源码分析—单例模式singleInstance
- 设计模式の单例模式
- 安卓之单例模式
- 安卓之单例模式讲解
- 匠牛社区AM5728 SDK与交叉编译工具安装
- 根据某表内容更新此表某字段
- C语言字符数组与字符串的使用及加结束符'\0'的问题
- 平面设计师之路1——基础
- JS——坑4
- 安卓设计模式の单例模式
- 搞人工智能必备“数学库”
- 给小米公司的建议
- 工具| 手把手教你信息收集之子域名收集器
- 推荐 | 一文读懂深度学习与机器学习的差异
- C语言——内存消耗测试程序
- sh
- go
- Typeface 指定字体样式