前记:本文主要是学习笔记,如有哪里写的不对,还希望大家指出,予以改正。
说起单例模式,现在网上百度一搜一大把,本文主要是参考拭心大神的文章,进行学习和总结。
接下来来说正事。
1、解释
所谓的单例模式就是保证某个类只能被创建一次,而且以后在使用这个类的时候只能使用这个类对象。比如电脑上的任务管理器、Android中的application等。
2、作用
单例模式就是为了保证某个状态一致性,在某个位置改变了该类对象的状态,在其他地方使用的时候引用最新的状态。
单例之-----懒汉模式
上代码:
public class TextActivity {
TextActivity inStance = null;
//防止通过构造器创建,将构造器改成私有的
private TextActivity() {
}
public TextActivity getInstance() {
if (inStance == null) {
inStance = new TextActivity();
}
return inStance;
}
}
注:
将构造器定义为私有的, 可以有效防止通过构造器创建对象。同时,这种方式虽然实现起来简单,但是在线程上是不安全的,当多线程同时访问时,由于线程的不确定性,可能会创建多个对象,在使用时产生混乱。
单例之-----懒汉模式的进化(加锁控制的单例模式)
为了避免上述问题(线程不安全),可以在懒汉模式的基础上增加同步锁进行控制。但是如果只是简单的锁控制,在多线程访问时,出现线程2需要在线程1访问完才能访问,线程3等待线程2......这样一直等待太耗时间,所以就进一步优化,只有在该类对象没有被创建的时候才进行锁控制,有实例对象的时候直接返回该实例(上代码):
public class TextActivity {
static TextActivity inStance = null;
//防止通过构造器创建,将构造器改成私有的
private TextActivity() {
}
public static TextActivity getInstance() {
if (inStance == null) {
createInstance();//使用同步锁控制
}
return inStance;
}
//同步锁控制
public synchronized static void createInstance() {
if (inStance == null) {
inStance = new TextActivity();
}
}
}
注:
这种方式虽然保证了实例的唯一性,但是在多线程的情况下并没有保证创建的先后顺序。正常情况下,我们是在主线程中对类对象进行创建,其他线程访问我们创建好的,这样前面的问题就不存在了,如果要在多线程中访问,就不安全,就要在类方法创建时进行初始化,而不是调用时才初始化。
单例之-----饿汉式单例
该模式使用了static的预先加载的特性
被static修饰的成员变量和成员方法独立于该类的任何对象,也就是说它不依赖特定的实例,被类的所有实例共享,只要这个类被加载了,java虚拟机就能根据类名在运行时数据区的方法区找到他们,因此static对象可以在它的任何对象创建之前访问,无需引用任何对象。
这种方式基于classloader机制,避免了多线程的同步问题,在类加载的同时就已经创建了一个静态的对象供系统使用,以后不会再改变,所以线程是安全的。在这种思路下就引发了新的单例模式的编写方法:
上代码:
public class TextActivity {
static TextActivity inStance = new TextActivity();
//防止通过构造器创建,将构造器改成私有的
private TextActivity() {
}
public static TextActivity getInstance() {
return inStance;
}
}
注:
这种方式有个缺点:不能从外部进行初始化,对象都是写死的,但是很多大牛都推荐这样写。
总结
单例模式的编写模式、方式多,但是可以根据实际情况选择适合自己应用场景的,大部分情况下是不会在多线程中使用的,不过也不排除这种情况。假如我们使用前两种方式,可以在主线程中创建实例,这样在多线程引用时就已经存在了类对象,就不会出现上文中提到的问题。所以解决问题重要的是有思路,解决问题的方式不是一成不变的。
外篇:(一起共同学习进步)
QQ群:541144061
微信群:加我好友,写好备注:android技术经验分享
image.png
网友评论