单例模式简介
本篇内容只是对单例模式简单介绍概念, 因为本篇文章着重不在此!
-
普通饿汉式(一般用
static final
修饰)初始化其外部类时即创建, 优点: 简单, 方便, 缺点: 如果遇到那些初始化比较耗损时空间, 或建立一些连接之类的时成本比较高, 这个时候可以考虑使用饿汉式.
-
懒汉式(双重锁判断)
即懒加载形式的单例, 即用即加载. 双重锁判断是大多初学者的常用单例模式,
-
懒汉式(静态内部类)
这个是我之前一直使用的一种方式, 但是每次使用都还是挺麻烦的, 还要建立一个内部类, 不够简单
-
饿汉式(枚举式)
这个我也经常用, 例如数据字典用这种方式再合适不过.
-
注册登记式
相当于一个单例模式的大集合, Spring中单例的实现方式, 在不使用Spring的时候我都会单独用一个类来实现注册登记式.
我的单例模式历程
初学单例模式的时候, 我了解到的是普通饿汉式
和懒汉式(双重锁判断)
, 并常常使用懒汉式(双重锁判断)
, 毕竟相对于饿汉式
来说高端大气上档次, 但是写的时候挺麻烦, 一般都会为每个单例实例
单独新建一个类, 有的时候还忘记加 volatile
关键字, 导致线程不安全.
后来我了解到懒汉式(静态内部类)
, 突然感到这种写法相对于懒汉式(双重锁判断)
更加简单, 而且很容易可以将多个懒汉式实例写在一个java文件中, 维护和管理起来比较方便, 之后我很长一段事件使用的就是这种模式.
但是顺着经验的增加, 我明白了, 绝大多数单例类实际上都没有必要使用饿汉式, 有的直接使用最简单的饿汉式就可以很好的满足需求, 除了遇到那些初始化比较耗损时空间, 或建立一些连接之类的情况, 其它的情况直接使用普通的饿汉式
就可以了, 尤其是和一些应届生共同开发的时候, 保持代码的简单更容易降低出错机率
, 至于初始化浪费的那点空间, 根本微不足道.
但是本着强迫症程序员的倔强, 我又不想放弃懒汉式
, 直到有一天, 我看到一种语言仅仅调用一个类的函数便很好的将一个对象变成了单例懒汉式(那种语言我忘记是什么了, .net, C#还是什么来着, 太久远记不清了), 于是我便想能不能用java实现一个单例懒汉式工具类, 于是便有了下面的类.
工具类LazySingleton.java
package com.github.cosycode.common.ext.hub;
import java.util.Objects;
import java.util.function.Supplier;
/**
* <b>Description : </b> 单例懒加载工具类
*
* @author CPF
* @since 1.0
* @date 2020/6/15
*/
public class LazySingleton<T> {
/**
* 单例模式仅仅保证引用可见性即可
*/
@SuppressWarnings("java:S3077")
private volatile T t;
private final Supplier<T> supplier;
public static <R> LazySingleton<R> of(Supplier<R> supplier) {
return new LazySingleton<>(supplier);
}
private LazySingleton(Supplier<T> supplier) {
Objects.requireNonNull(supplier, "构造器不能为空");
this.supplier = supplier;
}
/**
* 双重锁单例
*
* @return 值
*/
public T instance() {
T tmp