- 前言
- 一、单例模式是什么?
- 二、饿汉模式
- 1、饿汉定义
- 2、为什么说饿汉模式是线程安全的呢?
- 三、懒汉模式
- 1、懒汉定义
- 2、为什么说懒汉模式是线程不安全的呢?
- 3、双重检查锁定机制
- 四、饿汉式与懒汉式的优缺点
- 总结
前言
单例模式在很多面试题都出现过,单例模式能够保证一个类仅有唯一的实例,并提供一个全局访问点。而不用想要每个对象的时候就去new一个,这样浪费资源和空间
一、单例模式是什么?
平时使用的软件中,例如 回收站、线程池、文件系统等,都只有一个实例,这些都是单例模式的典型应用。
单例模式:确保某个类只有一个实例,并提供一个全局访问点来访问这个实例。
单例模式有三个要点:
1. 某个类只能有一个实例
2. 必须自行创建这个实例
3. 必须自行向整个系统提供这个实例。
以上三个要点提示着我们的代码编写需要注意,构造函数必须私有,否则在其他类中便可以调用构造函数创建实例,难以保证实例的唯一性
为什么要叫饿汉呢?这里可以理解为很饿,所以迫不及待地在类加载的时候就创建一个实例对象
//饿汉模式:(线程安全) class Singleton1 { // 静态私有成员变量 private static Singleton1 instance = new Singleton1(); // 私有构造函数 private Singleton1() { } // 静态公有工厂方法,返回唯一实例 public static Singleton1 getInstance() { return instance; } }2、为什么说饿汉模式是线程安全的呢?
答:因为在每次类加载的开始,该对象的实例就被创建了,线程要访问该对象一开始就拿到了这个唯一的对象,所以它是线程安全的
三、懒汉模式 1、懒汉定义和饿汉相对应,懒汉十分的懒,直到有线程需要访问该对象的时候,他才去判断是否已经有对象存在,如果没有,才再去创建对象
// 懒汉模式:(线程不安全,需要通过双重检查锁定机制控制) class Singleton2 { // 静态私有成员变量 private static Singleton2 instance = null; // 私有构造函数 private Singleton2() { } // 静态公有工厂方法,判断成员变量是否为空,不为空则实例化 public static Singleton2 getInstance() { if(instance == null) instance = new Singleton2(); return instance; } }2、为什么说懒汉模式是线程不安全的呢?
如果有两个线程AB要访问这个对象,拿对象的时候在if(instance == null) 前,实例都没有被创建,那么 A 会得到 true 的结果,但是此时调度算法选择 B 线程运行,那么当 B 执行 到 if(instance == null) 时得到的也是 true,z这样两个线程都会执行 instance = new Singleton2(); 从而创建了两个实例。
3、双重检查锁定机制为了将懒汉式变为线程安全的模式,就要采用双重检查锁定机制,该机制的原理是加一个同步锁(类锁),就可以防止多个线程同时创建对象,因为他们现在是互斥的访问
class Singleton3 { // 私有静态成员变量 private static volatile Singleton3 instance = null; // 私有构造函数 private Singleton3() { } // 共有静态工厂方法 public static Singleton3 getInstance() { // 判断 instance 是否为空,为空->加锁,创建实例(为了进程安全,再次判断),不为空->返回实例 if(instance == null) { synchronized (Singleton3.class) { if(instance == null) instance = new Singleton3(); } } return instance; } }四、饿汉式与懒汉式的优缺点
饿汉模式不需要考虑线程安全问题,调用速度和访问速度优于懒汉模式,但是由于它不管是否被调用都会提前创建类的实例,所以资源利用效率比较低,系统加载时间比较长。
懒汉模式实现了延迟加载,但是需要克服多个线程同时访问的问题,需要通过双重检查锁定机制进行控制,导致系统性能受到一定影响。
总结本章的内容是java单例模式的实现,为什么要使用单例模式可以参考
https://blog.csdn.net/love_java_cc/article/details/52161884
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)