这是我参与11月更文挑战的第21天,活动详情查看:2021最后一次更文挑战
设计模式之单例模式
前文
本文内容为对于单例模式的一些个人总结,并非代表权威,难免有不足之处,还请见谅。
什么是单例模式
单例模式顾名思义,也就是对于一个类,它的对象仅有一个,不会重复的创建对象。所有对于该类新建或获取对象的操作都会统一进行,操作的对象也是完全相同的对象。
单例模式的几种形式
饿汉式
饿汉式,可以理解为很饥饿,因此会在类加载时,即直接创建好对象,后面操作的对象也就是该对象。根据创建的过程中我们可以分析到,饿汉式可能存在的问题是在对象被利用前便创建出来,如果对象最终没有被利用,也就是整个程序运行过程中会存在垃圾对象不会被回收。
public class Singleton {
private Singleton(){
}
private static final Singleton instance = new Singleton();
private static Singleton getInstance(){
return instance;
}
}
懒汉式
懒汉式的单例模式,可以根据名字进行另一种理解。这个程序可能很慵懒,因此仅仅当程序执行到需要对象时,才进行单例模式的创建。因此,在创建前需要进行一次判断,防止对象已经被创建出来,再次创建会将原有的对象覆盖。
public class Singleton{
private Singleton(){
}
private static Singleton instance;
private static Singleton getInstance(){
if(instance == null){
instance = new Singleton();
}
return instance;
}
}
单例模式的多线程改造
对于饿汉式来说,由于是在程序启动阶段已经创建好,后续的程序只是调用该对象,不存在多线程同时创建对象的问题,因此不会存在线程安全问题。
而对于懒汉式来说,如果两个线程同时判断到对象为null,两个线程会同时创建对象,也就是会产生对象的覆盖,存在线程安全的问题。
那么对于懒汉式,我们可以用双重检测来进行改造。在判断对象为空时,需要增加锁,利用锁保证多线程不会同时执行。同时,当两个线程同时获取到锁后,第一个线程执行结束时,则第二个线程还需要进行一次判断,防止此时对象已经被前一个线程创建出来。因此我们还需要在这里使用volatile关键字,来保证变量在线程间可见。
public class Singleton{
private Singleton(){
}
private static volatile Singleton instance;
private static Singleton getInstance(){
if(instance == null){
synchronized (Singleton.class){
if(instance == null){
instance = new Singleton();
}
}
}
return instance;
}
}
后记
- 千古兴亡多少事?悠悠。不尽长江滚滚流。