一、单例模式是什么
单例模式指的是一种常用的软件设计模式,类创建单一实例以满足多方调用,即一个类只有一个对象实例
二、单例模式优缺点
优点
单例模式只构建单一实例,供多个方法使用,避免多个方法构造同个类多个对象,减少内存的开销。
缺点
单例模式没有接口,也没有抽象层,扩展性性差,如需扩展,需在原有代码上进行修改。
三、单例模式实现形式
1.懒汉模式
懒汉模式也就是“懒”,当需要时再创建实例,如下:
public class Singleton {
private Singleton() {}
private static Singleton single=null;
public static Singleton getInstance() {
if (single == null) {
single = new Singleton();
}
return single;
}
}
可见简单的不加锁的懒汉模式是线程不安全的
例如:A、B线程同时访问时,此时刚进来两者的single都为null,A线程还没到new Singleton(),此时B线程到了if (single == null)语句,判断到single为null,那么也new Singleton(),就导致生成两个实例
那么就来说说如何让他线程安全
1.加方法锁synchronized
public static synchronized Singleton getInstance() {
if (singleton == null) {
singleton = new Singleton();
}
return singleton;
}
或者
public static Singleton getInstance() {
synchronized (Singleton.class) {
if (singleton == null) {
singleton = new Singleton();
}
}
return singleton;
}
但是这样每次进来都会加锁,其实我们也就是再第一次进来实例后就不需要再实例了。那么可以再加一层判断不为空,即不是第一次进来,已创建实例,就不需要进行加锁创建实例。如下:
public static synchronized Singleton getInstance() {
if (singleton == null) {
synchronized (Singleton.class) {
if (singleton == null) {
singleton = new Singleton();
}
}
}
return singleton;
}
由于Java指令重排问题,优化实例中加入锁volatile
public class Singleton {
private static volatile Singleton singleton;
private Singleton(){}
public static Singleton getInstance() {
if (singleton == null) {
synchronized(Singleton.class) {
if (singleton == null) {
singleton = new Singleton();
}
}
}
return singleton;
}
}
稍微讲讲重排列
线程A,B同时访问,此时还未创建实例, A线程获取到锁,此时JVM为singleton分配内存,还未初始化,B线程进行判断singleton时,不为空,即返回,导致有空指针出现。volatile可以保证可见性,从而避免这种问题出现。
2.饿汉模式
饿汉模式即“饿”,它先创建实例,“饿”的时候,也就是方法调用它的时候,它就直接返回自身已经创建的实例返回。
public class Singleton {
private Singleton() {}
private static final Singleton single = new Singleton();
public static Singleton getInstance() {
return single;
}
}
3.两种模式类型对比
“懒汉”就是很“懒”,等调用再创建实例。“饿汉”是“饿”,它不懒,它先创建好实例,需要的时候直接返回。看了饿汉模式是否会觉得饿汉模式代码简洁,还线程安全,用起来非常方便。但是也会有它的缺点,懒汉模式也是有他的优点的。两种类型优缺点如下:
①.懒汉模式
优点: 减少内存的开销,需要时再创建
缺点: 需注意线程安全问题
②.饿汉模式
优点: 线程安全
缺点: 不用时自动创建好实例,占用内存
这样一看,如果是很注重内存分配的项目,则采用懒汉模式会更好,如果更注重代码简洁,不是很注重内存的项目,可采用饿汉模式。