JAVA的单例模式(singleton)

  • 一、什么是单例模式?
    • 1. 优点
    • 2. 缺点
    • 3. 使用场景
  • 二、什么是线程安全和非线程安全?
    • 1.线程安全
    • 2.非线程安全
    • 3.线程安全与不安全的本质区别
  • 三、单例模式的5种创建方式
    • 1.饿汉式
    • 2.懒汉式
    • 3.双重锁检测模式(Double Check Lock)
    • 4.静态内部类模式
    • 5.通过枚举实现单例模式

一、什么是单例模式?

单例模式是一个类只有一个实例对象。其构造函数是私有的,不能通过new方式创建实例对象。在整个程序的生命周期内都只存在一个单例类的实例对象,以静态方法或枚举返回唯一的实例化对象。

1. 优点

①在内存里只有一个实例,减少了内存的开销,尤其是频繁的创建和销毁实例(比如管理学院首页页面缓存)。
② 避免对资源的多重占用(比如写文件操作)。

2. 缺点

没有接口,不能继承,与单一职责原则冲突,一个类应该只关心内部逻辑,而不关心外面怎么样来实例化。

3. 使用场景

①要求生产唯一序列号。
② WEB 中的计数器,不用每次刷新都在数据库里加一次,用单例先缓存起来。
③ 创建的一个对象需要消耗的资源过多,比如 I/O 与数据库的连接等。

注意事项:getInstance() 方法中需要使用同步锁 synchronized (Singleton.class) 防止多线程同时进入造成 instance 被多次实例化

二、什么是线程安全和非线程安全?

1.线程安全

线程安全就是多线程访问时,采用了加锁机制,当一个线程访问某一个类的某个数据时,进行保护,其他线程不能进行访问直到该线程读取完,其他线程才可使用。不会出现数据不一致或者数据污染的情况。

2.非线程安全

线程不安全就是不提供数据访问保护,有可能出现多个线程先后更改数据,从而导致数据不一致,造成所得到的数据是脏数据

3.线程安全与不安全的本质区别

线程安全与不安全的本质区别在于对于共享资源的访问上的执行效果.安全线程在处理共享资源时效果具有原子性,即必须等到当前线程访问结束后别的线程才能继续访问.而非安全线程则任何时候都可以抢占cpu的使用权,导致的结果就是线程共享资源由于多线程争抢访问导致的数据错误问题.

三、单例模式的5种创建方式

1.饿汉式

//类加载时就创建一次实例,避免了多线程问题,但是还在使用就创建了对象,浪费内存
//线程安全
public class Singleton {private Singleton() {} private static Singleton instance = new Singleton(); public static Singleton getInstance() {return instance;}
}

2.懒汉式

//优点:需要的时候才进行创建
//缺点:线程不安全,多线程时会创建多个实例
public class Singleton {private Singleton() {}private static Singleton instance = null;public static Singleton getInstance() {if (null == instance) {instance = new Singleton();}return instance;}
}
//优点:线程安全,但是在多线程情况下还是有可能出现不安全的情况,
//threadA和threadB同时执行到if (null == instance)时就与可以出现创建多个实现
//缺点:添加了synchronized的函数比一般方法慢得多,若多次调用getInstance,则累积的性能损耗特别大。
public class Singleton {private Singleton() {}private static Singleton instance = null;public static synchronized Singleton getInstance() {if (null == instance) { instance = new Singleton(); }return instance;}
}

3.双重锁检测模式(Double Check Lock)

//多线程情况下还是可能出现创建多个实例情况,主要是因为jvm对命令进行重排序优化,而导致创建多个实例的情况。
public class Singleton {private Singleton() {}private static Singleton instance = null;public static Singleton getInstance() {if (null == instance) {synchronized (Singleton.class) {if (null == instance) {instance = new Singleton();}}}return instance;}
}
//优点:线程安全,volatile关键词主要是保证多线程之间的可见性,保证线程在每次取值volatile变量都是最新值
//volatile关键字主要是禁止命令重排序的,但是volatile不是原子性的
public class Singleton {private static volatile Singleton instance = null;private Singleton() {}public static Singleton getInstance() {if (null == instance) {synchronized (Singleton.class) {if (null == instance) {instance = new Singleton();}}}return instance;}
}

4.静态内部类模式

  public class Singleton {private Singleton() {}private static Singleton getInstance() {return SingletonHolder.instance;}private static class SingletonHolder {//静态变量值会初始化一次private static Singleton instance = new Singleton();}
}

5.通过枚举实现单例模式

//优点:既能避免多线程同步问题,又能防止反序列化重新创建新的对象
public enum Singleton {INSTANCE;public void doSimthing(){}
}

参考文献:
Java单例模式的5种实现方法
单例模式
Java创建线程安全的单例singleton
volatile关键词
什么是指令重排序?为什么要重排序

Java创建单例模式(singleton)的几种实现方式相关推荐

  1. Java 创建一个线程的三种方式

    Java 创建一个线程的三种方式 更多内容,点击了解: https://how2j.cn/k/thread/thread-start/353.html 创建多线程有3种方式,分别是继承线程类,实现Ru ...

  2. Java框架篇---spring aop两种配置方式

    Java框架篇---spring aop两种配置方式 第一种:注解配置AOP 注解配置AOP(使用 AspectJ 类库实现的),大致分为三步:  1. 使用注解@Aspect来定义一个切面,在切面中 ...

  3. Java中List集合的三种遍历方式(全网最详)

    Map集合:链接: Map集合的五种遍历方式及Treemap方法 Set集合:链接: Java中遍历Set集合的三种方法 TreeSet集合:链接: Java深入了解TreeSet,和迭代器遍历方法 ...

  4. java foreach hashmap_在 Java 中遍历 HashMap 的5种最佳方式

    在本文中,我们将通过示例讨论在 Java 上遍历  HashMap  的五种最佳方式. 使用  Iterator  遍历 HashMap EntrySet 使用  Iterator  遍历 HashM ...

  5. Java面试之多线程:Java创建多线程为什么只有一种方式?

    关于线程的创建,其实我一直都有话说,于是今天,我来开个头.今天依旧一样,长话短说,只谈创建多线程.你好,我是fntp!今天要跟大家分享的是博主最近面试Java实习所遇到的一些问题!那就是经常性被问到的 ...

  6. java servlet接口开发_servlet三种实现方式之一实现servlet接口

    servlet有三种实现方式: 1.实现servlet接口 2.继承GenericServlet 3.通过继承HttpServlet开发servlet 第一种示例代码如下(已去掉包名): import ...

  7. Java本地高性能缓存的几种实现方式

    Java缓存技术可分为远端缓存和本地缓存,远端缓存常用的方案有著名的redis和memcache,而本地缓存的代表技术主要有HashMap,Guava Cache,Caffeine和Encahche. ...

  8. c++单例模式线程安全几种实现方式

    c++编程中,单例模式经常用到,单例模式有懒汉模式和饿汉模式两种. 懒汉模式直接采用静态变量,但是占用内存. 饿汉模式,根据需要动态生成,但是多个线程同时调用,存在线程安全问题. 下面主要总结饿汉模式 ...

  9. java中List集合的几种遍历方式

    本文中我们给出了List集合中的四种遍历方式,分别是for循环,迭代器循环,代码及相应的注释如下: package d1_collection;import java.util.*;public cl ...

最新文章

  1. Teched 2010
  2. 各种操作系统ping时的TTL值
  3. maven项目配置Jetty服务器
  4. resultType 和resultMap 的区别?
  5. TDSQL 全时态数据库系统 -- 典型案例
  6. Win7旗舰版系统时间不准确怎么办
  7. Java定时任务解决方案
  8. oracle ignore_Oracle 数据库常用操作语句,速速收藏
  9. java实现微信公众平台中的字典排序
  10. linux mysql配置修改_【Mysql】linux下mysql的配置修改
  11. java 解析mp4文件头_视频文件头解析--MP4-获取mp4 文件信息
  12. Java语言课程设计——简易计算器(详细含报告和源代码)
  13. 小米 线刷 android,小米10 Android 11 Beta 1线刷包已放出,安卓11/MIUI 12二选一
  14. Python教你实现微信防撤回~
  15. c++学习记录之多态
  16. windows UWP 应用使用系统代理
  17. 福州船政计算机专业多少钱,福建船政交通职业学院怎么样排名多少?特色专业?录取分数线及收费...
  18. 正则去掉首尾空格以及首尾的
  19. 新概念1、2英语学习计划
  20. NTP And System Clock Maintenance

热门文章

  1. 魔兽世界怀旧服 八区最新服务器推荐,魔兽世界怀旧服选择哪一个服务器好[多图]...
  2. 【技术文档】centernet(姿态估计)
  3. 2021年上半年全球首席执行官任命达到创纪录水平,女性首席执行官翻了一番|美通社头条...
  4. 使用Java设计简单的画图工具
  5. Gradle 7.4 包上传私服
  6. android 小米加载大图,Android手机拍照或从本地相册选取图片设置头像。适配小米、华为、7.0...
  7. 数据中心交换机与普通交换机有什么不同?
  8. 通俗理解 set,dict 背后的哈希表
  9. windows电脑cmd命令查看网卡的物理地址(mac地址)
  10. 2022物联网工程保研经历分享(中科院计算所、中科院软件所、中科大、南大、华中科技大学、北航、哈工大、中山大学等)