单例模式
是设计模式的中的一种。所谓单例模式,就是就是整个系统中对象仅此一个,不会有重复的对象生成。
1. 懒汉式
顾名思义,就是比较懒,当你使用的我现场去创建对象。
// 单例对象
class SingleObject{
private static SingleObject instance;
//构造方法私有化
private SingleObject(){
System.out.println("我是 SingleObject 的构造方法");
}
public static SingleObject getInstance() {
if(instance==null) {
instance = new SingleObject();
return instance;
}
return instance;
}
}
2. 饿汉式
顾名思义,就是时刻保持警惕,一上来就把对象给你创建好,就等着你使用。
// 单例对象
class SingleObject{
private static SingleObject instance = new SingleObject();;
//构造方法私有化
private SingleObject(){
System.out.println("我是 SingleObject 的构造方法");
}
public static SingleObject getInstance() {
return instance;
}
}
注意:在单线程中 懒汉式 和 饿汉式 可以解决问题,但是在多线程的环境中,这么些是有问题的!
为了看着清晰,我们现场来测试一下:
// 单例对象
class SingleObject{
private static SingleObject instance;
//构造方法私有化
private SingleObject(){
System.out.println( Thread.currentThread().getName() + " 我是 SingleObject 的构造方法");
}
public static SingleObject getInstance() {
if(instance == null) {
instance = new SingleObject();
return instance;
}
return instance;
}
}
// 单例模式:饿汉式多线程测试
public class SingleDemo {
public static void main(String[] args) {
for (int i = 0; i < 10; i++) {
new Thread(()->{
SingleObject.getInstance();
},i+"").start();
}
}
}
执行结果:
所以结合多线程环境下,创建了一种新的模式
3. (DCL)双检锁
// 单例对象
class SingleObject{
private static SingleObject instance;
//构造方法私有化
private SingleObject(){
System.out.println( Thread.currentThread().getName() + " 我是 SingleObject 的构造方法");
}
public static SingleObject getInstance() {
if(instance == null) {
synchronized (SingleObject.class) {
if(instance == null) {
instance = new SingleObject();
return instance;
}
}
}
return instance;
}
}
双检锁(DCL),又叫双重校验锁,综合了懒汉式和饿汉式两者的优缺点整合而成。但是这个机制不一定线程安全,原因是因为它有指令重排序的存在,所以,需要加上 volatile 来禁止指令重排序。如果不了解指令重排,可以看看博客:volatile 关键字
所以说需要禁止指令重排,保证多线程下的语义一致性,如果不加,就有一定的几率出现线程不安全问题。
4. volatile 版本 DCL(最完美)
// 单例对象(双检锁+volatile)推荐使用
class SingleObject{
// 加上 volatile 关键字,禁止指令重排
private static volatile SingleObject instance;
//构造方法私有化
private SingleObject(){
System.out.println( Thread.currentThread().getName() + " 我是 SingleObject 的构造方法");
}
public static SingleObject getInstance() {
if(instance == null) {
synchronized (SingleObject.class) {
if(instance == null) {
instance = new SingleObject();
return instance;
}
}
}
return instance;
}
}