设计模式5——单例模式

如果饿了就吃,困了就睡,渴了就喝,人生就太无趣了


1.定义

1.1 概念

确保一个类只有一个实例,并提供一个全局访问点。简单来说:将构造器私有化,并在静态方法中初始化该类的静态变量。

1.2 类图

如图1,定义一个该类的私有静态变量uniqueInstance,并将构造器定义为private(在图中没有显示),通过静态方法getInstance()uniqueInstance初始化并返回该实例。

在这里插入图片描述

2.单例模式各种类型。

2.1 经典类型

在使用时会被创建,但是在并发模式中会出现问题。

public class Singleton {
    private static Singleton uniqueInstance;

    private Singleton(){}

    public static Singleton getInstance(){
        if(uniqueInstance==null){
            uniqueInstance=new Singleton();
        }
        return uniqueInstance;
    }
}

2.2 同步锁类型

getInstance变成同步方法。在方法声明中加入 synchronized关键字。

synchronized:让每个线程进入该关键字修饰的方法前,要先等待其他线程离开后才能访问。


问题:这样每次访问getInstance()都会需要同步,但实际上只要uniqueInstance被设置好后就不需要同步,只是第一次访问需要同步。如果程序需要大量访问getInstance()方法,就会大大降低性能。

public class Singleton {
    private static Singleton uniqueInstance;

    // other useful instance variables here

    private Singleton() {}

    public static synchronized Singleton getInstance() {
        if (uniqueInstance == null) {
            uniqueInstance = new Singleton();
        }
        return uniqueInstance;
    }

}

2.3 急切类型

uniqueInstance变量初始化交给静态初始化器。JVM将保证线程安全,因为JVM在加载这个类时会马上创建一个唯一的单间实例,JVM保证任何线程访问uniqueInstance前,一定会先创建此实例。

public class Singleton {
    private volatile static Singleton uniqueInstance=new Singleton();
    private Singleton() {}

    public static Singleton getInstance(){
        return uniqueInstance;
    }
}

2.4 双重检查加锁类型

使用双重检查加锁(double-checked locking),首先检查实例是否已经创建了,如果尚未创建,再进行同步。这样就只有第一次才会同步。

volatile:

  • 类型修饰符。
  • 保证了不同线程对这个变量进行操作时的可见性。例如果对变量值进行改变,对其他线程是立即可见。(实现可见性)
  • 禁止进行指令重排序(实现有序性)
  • 保证对单次读/写的原子性。i++ 这种操作不能保证原子性。

这样就确保了uniqueInstance被初始化时,多个线程能正确处理uniqueInstance变量。

  1. getInstance()方法中的第一个if保证在uniqueInstance初始化后,避免同步。
  2. getInstance()方法中的第二个if保证在线程a,b同时进入后,能够有序执行同步锁中的内容。没有第二个if也是不能保证单例的。
public class Singleton {
    private volatile static Singleton uniqueInstance;

    private Singleton() {
    }

    public static Singleton getInstance() {
        if (uniqueInstance == null) {
            synchronized (Singleton.class) {
                if (uniqueInstance == null) {
                    uniqueInstance = new Singleton();
                }
            }
        }
        return uniqueInstance;
    }
}

2.5 其他类型

没有搞定,也就不敢乱写。

发布了11 篇原创文章 · 获赞 2 · 访问量 365

猜你喜欢

转载自blog.csdn.net/weixin_41938180/article/details/104251685