单例模式
来源:互联网 发布:店铺seo是什么意思 编辑:程序博客网 时间:2024/06/07 01:42
概念
某个类只有一个实例,而且自行实例化并向整个系统提供这个实例。单例模式主要有恶汉模式和懒汉模式。
恶汉模式
恶汉模式主要是在加载类的时候,就会实例化对象,具体代码如下:
public class Person { private String name; private int age; private static final Person mPerson = new Person(); private Person(){} public static Person getInstance(){ return mPerson; } public String getName() { return name; } public void setName(String name) { this.name = name; } public int getAge() { return age; } public void setAge(int age) { this.age = age; }}
恶汉模式由于在加载类的时候就已经对对象进行初始化,因此这种实现方式不存在多线程不安全的问题。
懒汉模式
懒汉模式是声明一个静态对象,是在用户第一次调用获取对象时进行初始化。具体代码如下:
public class Person { private String name; private int age; private static Person mPerson = null; private Person(){} public static Person getInstance(){ if(mPerson == null){ synchronized (Person.class){ if(mPerson == null){ mPerson = new Person(); } } } return mPerson; } public String getName() { return name; } public void setName(String name) { this.name = name; } public int getAge() { return age; } public void setAge(int age) { this.age = age; }}
该写法亮点主要在于getInstance中的两次判空以及synchronized的用法。第一次判空这个很好理解,当单例对象不为空直接返回;使用synchronized主要是为了保证初始化对象时同步。第二次判空处理是什么意思呢?这个理解有点难度,需要从汇编的角度去思考。mPerson = new Person() 对应的汇编指令其实有多条,大致做了三件事情。
(1)、给Person的实例分配内存;
(2)、调用构造函数,初始化成员变量;
(3)、将mPerson对象指向分配的内存空间,此时mPerson就不是null了。
由于Java编译器允许处理器乱序执行,上面的2、3是无法保证顺序的,如果A线程先执行了3,此时B线程开始执行了,发现mPerson不为空,直接取走,在使用成员变量就会出错,因此上面这种单例实现方式还是存在一定问题的,而且这种错误很难重现。
下面给出另外一种实现方案,防止上面问题产生:
public class Person { private String name; private int age; private Person(){} public static Person getInstance(){ return PersonHolder.mPerson; } public String getName() { return name; } public void setName(String name) { this.name = name; } public int getAge() { return age; } public void setAge(int age) { this.age = age; } private static class PersonHolder{ private static final Person mPerson = new Person(); }}
当第一次加载Person类时,并不会初始化mPerson,只有当第一次调用getInstance方法时才会初始化mPerson,这种方式不仅可以保证线程安全,也能保证单例对象的唯一性,同时也延迟了单例的实例化,所以上面这种方式才是推荐的使用方式。
对比恶汉模式与懒汉模式
1、恶汉模式在加载类的时候就已经初始化了对象,在类加载时就完成了初始化,所以类加载较慢同时这带来了内存的提前消耗;
2、懒汉模式在第一次需要的时候才会申请内存,这导致第一次加载的时候稍有缓慢,同时也要注意多线程的安全性,但是可以减少内存空间的使用。
- 单例、单例模式
- 单例模式-多线程单例模式
- 单件模式(单例模式)
- 设计模式------单例模式
- 设计模式------单例模式
- 设计模式-单例模式
- 设计模式 - 单例模式
- 设计模式---单例模式
- 设计模式---单例模式
- PHP模式-单例模式
- 【设计模式】单例模式
- 设计模式-单例模式
- 设计模式----单例模式
- 设计模式--单例模式
- 设计模式-单例模式
- 单例模式(单子模式)
- 设计模式-单例模式
- [设计模式] 单例模式
- PostgreSQL的JDBC驱动和URL
- AndroidStudio汉化
- 既然你选择,那么尊重你的选择
- 单词词频统计降序排序(代码贴)
- 微信小程序wx:key和wx:for问题
- 单例模式
- GameEntity(五)—— INpc
- Linux下Nginx的安装
- Inno Setup入门(八)——有选择性的安装文件
- C++中四种类型转换符:static_cast、dynamic_cast、reinterpret_cast和const_cast要点解析
- 移植gdb到海思3716板子的方法
- ViewPager切换Fragment时ListView数据不更新
- ImageTag 安装
- mariadb linux二进制tar包安装