设计模式——单例模式
介绍
单例(Singleton Pattern)是设计模式中最简单的一种。属于创建型模式
。它提供了一种创建对象的最佳方式,即内存中只有一个实例。也就是不会有人使用 new Singleton()
来生成一个新的对象。
意图
保证一个类仅有一个实例,并提供一个访问它的全局方法。
解决
一个全局使用的类频繁的创建与销毁。
优点
-
内存中只有 一个实例,减少了内存开销,避免了频繁的创建及销毁实例;
-
避免对资源的多重占用(写文件操作);
缺点
没有接口,不能继承,与单一原则冲突,一个类应该只关心内部逻辑,而不关系外部怎样实例化。
使用场景
-
系统产生唯一序列号;
-
WEB中的计数器,不用每次刷新在数据库中加一次,使用单例先缓存起来;
UML
示例
-
最常用的一种,也是最简单的一种
饿汉模式:(推荐)
/* * 功能描述: * 〈饿汉式单例模式 * 类加载到内存后,就实例化一个单例,JVM保证线程安全 * 简单实用,推荐使用 * 缺点:不管用到与否,类装载时完成实例化。 * 〉 * * @author : geoary * @date : 2019/12/10 21:33 */ public class Mgr01 { private static final Mgr01 INSTANCE = new Mgr01(); // 私有的构造函数 private Mgr01(){ } // 获取唯一对象实例 public static Mgr01 getInstance(){ return INSTANCE; } public static void main(String[] args) { Mgr01 mgr01 = Mgr01.getInstance(); Mgr01 mgr02 = Mgr01.getInstance(); System.out.println(mgr01 == mgr02); } }
-
懒加载模式1:
/** * 功能描述: * 〈懒加载 * 虽然达到了按需初始化的目的,但是带来了线程不安全问题 * 〉 * * @author : geoary * @date : 2019/12/10 21:53 */ public class Mgr03 { private static Mgr03 INSTANCE; private Mgr03() { } public static Mgr03 getInstance() { if (INSTANCE == null) { try { Thread.sleep(1); } catch (Exception e) { e.printStackTrace(); } INSTANCE = new Mgr03(); } return INSTANCE; } public static void main(String[] args) { for (int i = 0; i < 100; i++) { /*new Thread(new Runnable() { @Override public void run() { System.out.println(Mgr03.getInstance().hashCode()); } }).start();*/ new Thread(() -> System.out.println(Mgr03.getInstance().hashCode())).start(); } } }
-
懒加载模式2:
/** * 功能描述: * 〈懒加载 * 通过 synchronized 解决线程问题,但是效率下降 * 〉 * * @author : geoary * @date : 2019/12/10 21:59 */ public class Mgr04 { private static Mgr04 INSTANCE; private Mgr04(){ } public static synchronized Mgr04 getInstance(){ if (INSTANCE == null){ try { Thread.sleep(1); }catch (Exception e){ e.printStackTrace(); } INSTANCE = new Mgr04(); } return INSTANCE; } public static void main(String[] args) { for (int i=0;i<100;i++){ new Thread(()-> System.out.println(Mgr04.getInstance().hashCode())).start(); } } }
-
静态内部类
/** * 功能描述: * 〈静态内部类 * jvm 保证单例 * 〉 * * @author : geoary * @date : 2019/12/10 22:12 */ public class Mgr07 { private Mgr07(){ } private static class Mgr07Holder{ private final static Mgr07 INSTANCE = new Mgr07(); } public static Mgr07 getInstance(){ return Mgr07Holder.INSTANCE; } public static void main(String[] args) { for (int i=0; i<100; i++){ new Thread(()-> System.out.println(Mgr07.getInstance().hashCode())).start(); } } }
以上提供了几种实现单例模式的方式,其中最实用的是第一个
饿汉模式
,虽然会在类装载的时候完成实例化,但是使用简单而且线程安全。
应用场景demo
- 全局序列生成器
Singleton.java
package cn.geoaryblog.design.cretedg.single;
public class Singleton {
private static final Singleton INSTANCE = new Singleton();
private int num = 0;
private String name = "默认姓名";
public static Singleton getInstance() {
return INSTANCE;
}
// 获取序列
public static int getNextSeq(){
INSTANCE.num += 1;
return INSTANCE.num;
}
}
SingleMain.java
package cn.geoaryblog.design.cretedg.single;
public class SingleMain {
public static void main(String[] args) {
// 多个线程是否调用同一个实例
for (int i = 0; i < 20; i++) {
new Thread(() -> {
System.out.println("线程查询到的序列是:" + Singleton.getNextSeq());
}).start();
}
}
}
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 地球OL攻略 —— 某应届生求职总结
· 周边上新:园子的第一款马克杯温暖上架
· Open-Sora 2.0 重磅开源!
· 提示词工程——AI应用必不可少的技术
· .NET周刊【3月第1期 2025-03-02】