前言
通过单例模式可以保证系统中一个类只有一个实例。即一个类只有一个对象实例
一、简介
对于系统中的某些类来说,只有一个实例很重要,例如,一个系统中可以存在多个打印任务,但是只能有一个正在工作的任务。
如何保证一个类只有一个实例并且这个实例易于被访问呢?定义一个全局变量可以确保对象随时都可以被访问,但不能防止我们实例化多个对象。一个更好的解决办法是让类自身负责保存它的唯一实例。这个类可以保证没有其他实例被创建,并且它可以提供一个访问该实例的方法。
二、特点
1.此类只能有一个实例;
2.必须自行创建这个实例;
3.必须自行向整个系统提供这个实例。
三、单例模式的三种形式
1.饿汉式
在第一次调用的时候实例化自己;这种方式是最基本的实现形式。
但是也存在很大的问题:不支持多线程,所以严格意义上讲不应称为单例模式。
代码示例:
/**
* @projectName: ref-comet
* @package: com.xiangxue.singleton
* @className: Singleton
* @author: sunyingtao
* @description: 饿汉式
* @date: 2022/11/29 21:53
* @version: 1.0
*/
public class Singleton {
//构造函数私有化
private Singleton() {
}
private static Singleton singleton = new Singleton();
public static Singleton getSingleton(){
return singleton;
}
}
2.懒汉式
在第一次调用的时候实例化自己;能够在多线程中很好的工作,但是效率很低,99%情况下不需要同步
优点:第一次调用时才初始化,避免内存浪费
缺点:必须加锁才能保证单例,但加锁会影响效率
代码示例:
/**
* @projectName: ref-comet
* @package: com.xiangxue.singleton
* @className: Singleton
* @author: sunyingtao
* @description: 懒汉式
* @date: 2022/11/29 21:53
* @version: 1.0
*/
public class Singleton {
//构造函数私有化
private Singleton() {
}
private static Singleton singleton = null;
//构建实例化方法
public static Singleton getSingleton(){
if(singleton == null){
singleton = new Singleton();
}
return singleton;
}
}
3.双重锁的形式
此模式将同步内容放到了if内部,提高了执行的效率,不必每次获取对象时都进行同步,只有第一次才同步,创建了以后就没必要了。
所以如果面对高并发的情况,而且采用的是懒汉模式,最好的选择就是双重判断加同步的方式。
代码示例:
/**
* @projectName: ref-comet
* @package: com.xiangxue.singleton
* @className: Singleton
* @author: sunyingtao
* @description: 双重锁
* @date: 2022/11/29 21:53
* @version: 1.0
*/
public class Singleton {
//构造函数私有化
private Singleton() {
}
private static Singleton singleton = null;
public static Singleton getSingleton(){
//先检查实例是否存在,如果不存在才执行下面语句进行创建实例
if(singleton == null){
//加锁,线程安全的创建实例
synchronized (Singleton.class){
if(singleton == null){
//再次检查实例是否存在,还是不存在才进行创建实例
singleton = new Singleton();
}
}
}
return singleton;
}
}