使用SpringBoot开发单体应用的高效技巧
2026/6/20 19:07:05
Intent: Ensure a class only has one instance, and provide a global point of access to it. – 《Design Patterns: Elements of Reusable Object-Oriented Software》
翻译:
意图:保证一个类仅有一个实例,并提供一个访问它的全局访问点
理解:
采取一定的方法使得某个类在整个系统中,有且仅有一个实例
与定义适配,某个类没有状态的概念,仅需要有一个全局唯一的实例,比如各种工厂类、管理类等
饿汉顾名思义,很饿,想提供者赶紧做好
写法1:静态常量写法
/** * @Description 单例示例 饿汉-静态常量 * @Author bigHao * @Date 2025/12/17 */publicclassSingleton{// 2.静态常量,类加载时便创建privatestaticfinalSingletoninstance=newSingleton();// 1.构造方法私有privateSingleton(){}// 3.只暴露一个公共静态方法,返回实例/** * @return Singleton 单例 * @description 获取单例 * @author bigHao * @date 2025/12/17 **/publicstaticSingletongetInstance(){returninstance;}}写法2:静态代码块写法
/** * @Description 单例示例 饿汉-静态代码块 * @Author bigHao * @Date 2025/12/17 */publicclassSingleton{privatestaticfinalSingletoninstance;// 静态常量,静态块加载static{instance=newSingleton();}privateSingleton(){}/** * @return Singleton 单例 * @description 获取单例 * @author bigHao * @date 2025/12/17 **/publicstaticSingletongetInstance(){returninstance;}}调用方式:都是通过Class.获取实例方法
publicclassTest{staticvoidmain(){// 调用方只能通过暴露的方法调用,无法new的方式创建实例Singletoninstance=Singleton.getInstance();}}需要的时候再创建实例
/** * 单例示例 懒汉-线程不安全 */publicclassSingleton{privatestaticSingletoninstance;privateSingleton(){}/** * @return Singleton 单例 * @description 获取单例-线程不安全 * @author bigHao * @date 2025/12/17 **/publicstaticSingletongetInstance(){// 非原子操作,多线程场景会有多个线程进入到if内,从而创建多个实例if(instance==null){instance=newSingleton();}returninstance;}}多线程场景,可能会有多个线程同时执行if中的代码,创建多个实例
测试
/** * @Description 测试单例-懒汉-线程不安全 * @Author bigHao * @Date 2025/12/17 */publicclassTest{staticvoidmain(){// 测试线程不安全Set<String>instanceSet=newHashSet<>(100);// 多线程获取100次实例for(inti=0;i<100;i++){newThread(()->{instanceSet.add(Singleton.getInstance().toString());}).start();}// 因为set会去重,这里如果size不为1,意味着线程不安全,多个实例System.out.println(STR."instance size \{instanceSet.size()} 线程是否安全: \{1 == instanceSet.size()} ");// false}}静态方法加锁
/** * @Description 单例示例 懒汉-同步方法 * @Author bigHao * @Date 2025/12/17 */publicclassSingleton{privatestaticSingletoninstance;privateSingleton(){}/** * @return Singleton 单例 * @description 获取单例-同步方法 * @author bigHao * @date 2025/12/17 **/publicstaticsynchronizedSingletongetInstance(){// 只实例化一次if(instance==null){instance=newSingleton();}returninstance;}}/** * @Description 单例示例 双重检查+禁止指令重排 * @Author bigHao * @Date 2025/12/17 */publicclassSingleton{// volatile 禁止JVM对这个对象涉及到的代码重排序privatestaticvolatileSingletoninstance;privateSingleton(){}/** * @return Singleton 单例 * @description 获取单例-双重检查 * @author bigHao * @date 2025/12/17 **/publicstaticSingletongetInstance(){// 第一次判断示例是否存在;多线程场景下会放过一些线程if(instance==null){// 再次判断,针对被放过的线程,这里加锁进行等待synchronized(Singleton.class){if(instance==null){instance=newSingleton();}}}returninstance;}}利用静态内部类的机制,JVM帮助实现:
/** * @Description 单例示例 静态内部类 * @Author bigHao * @Date 2025/12/17 */publicclassSingleton{privateSingleton(){}// 静态内部类privatestaticclassSingletonInstance{privatestaticfinalSingletonINSTANCE=newSingleton();}/** * @return Singleton 单例 * @description 获取单例-静态内部类 * @author bigHao * @date 2025/12/17 **/publicstaticSingletongetInstance(){returnSingletonInstance.INSTANCE;}}利用枚举机制,JVM帮助实现:
/** * @Description 单例示例 枚举 * @Author bigHao * @Date 2025/12/17 */publicenumSingleton{INSTANCE;publicvoidmockMethod(){System.out.println("use success.");}}调用
/** * @Description 单例测试 枚举 * @Author bigHao * @Date 2025/12/17 */publicclassTest{staticvoidmain(){Singletoninstance=Singleton.INSTANCE;instance.mockMethod();}}jdk中Runtime类使用的就是经典的单例模式(饿汉式)