通俗的讲,单例模式就是确保只有一个实例,并且自动实例化并且向整个系统提供这个实例。话不多说,直接上代码:
public class SingletonModel {
// 自己内部先定义一个空对象
private static SingletonModel singletonModel = null;
//私有化构造方法,防止被实例化
private SingletonModel() {
}
// 提供一个方法返回该对象
public static SingletonModel getInstance() {
if (null == singletonModel) {
singletonModel = new SingletonModel();
}
return singletonModel;
}
}
这种属于懒汉式单例模式,但存在线程安全问题,假如一个线程1执行到 singletonModel = new SingletonModel()时,但还没有获得对象(对象的初始化时需要时间的),第二个线程2获得的条件也为真,于是也进入了实例化new SingletonModel()了,这样内存中就有两个对象了,解决方法如下:
public class SingletonModel {
// 自己内部先定义一个空对象
private static SingletonModel singletonModel = null;
//私有化构造方法,防止被实例化
private SingletonModel() {
}
// 提供一个方法返回该对象
public static synchronized SingletonModel getInstance() {
if (null == singletonModel) {
singletonModel = new SingletonModel();
}
return singletonModel;
}
}
在获取单例对象的方法上面加了个 synchronized 关键字,这样就能解决线程安全问题了,但效率不高,我们来改进一下:
public class SingletonModel {
// 自己内部先定义一个空对象
private static SingletonModel singletonModel = null;
//私有化构造方法,防止被实例化
private SingletonModel() {
}
// 提供一个方法返回该对象
public static SingletonModel getInstance() {
if (null == singletonModel) {
synchronized (SingletonModel.class) {
if (null == singletonModel) {
singletonModel = new SingletonModel();
}
}
}
return singletonModel;
}
}
这样效率就大大的提高了,那么,为什么要加两次判断呢?其实这判断是有目的的,第一层判断如果 singletonModel 实例不为空,那皆大欢喜,说明对象已经被创建过了,直接返回该对象即可,不会走到 synchronized 部分,所以singletonModel 对象被创建了之后,不会影响到性能。
第二层判断是在 synchronized 代码块里面,为什么要再做一次判断呢?假如 singletonModel 对象是 null,那么第一层判断后,肯定有很多线程已经进来第一层了,那么即使在第二层某个线程执行完了之后,释放了锁,其他线程还会进入 synchronized 代码块,如果不判断,那么又会被创建一次,这就导致了多个班长对象的创建。所以第二层起到了一个防范作用。
也可以采用内部类的方式来解决,JVM内部的机制能够保证当一个类被加载时,这个类的加载过程是线程互斥的。这样当我们第一次调用 getInstance() 方法时,JVM能够保证 instance 实例只会被创建一次,且把赋值给 instance 的内存初始化完毕,代码如下:
public class SingletonModel {
//私有化构造方法,防止被实例化
private SingletonModel() {
}
/**
* 使用一个内部类来维护单例
*/
private static class SingletonFactory {
private static SingletonModel instance = new SingletonModel();
}
// 获取实例
public static SingletonModel getInstance() {
return SingletonFactory.instance;
}
}
当然,单例模式还有一种饿汉式创建,简单粗暴,比较省事,代码如下:
public class SingletonModel {
//1.自己内部new一个
private static SingletonModel singletonModel = new SingletonModel();
//2.私有构造函数,防止被实例化
private SingletonModel() {
}
//3.提供一个公共接口,用来返回刚刚new出来的对象
public static SingletonModel getInstance() {
return singletonModel;
}
}
恭喜你,学会了单例模式,喜欢的关注一波啦~~