1.基本介绍
单例模式(Singleton Pattern)是 Java 中最简单的设计模式之一。这种类型的设计模式属于创建型模式,它提供了一种创建对象的最佳方式。
这种模式涉及到一个单一的类,该类负责创建自己的对象,同时确保只有单个对象被创建。这个类提供了一种访问其唯一的对象的方式,可以直接访问,不需要实例化该类的对象。
2.实现方式
通常单例模式在Java语言中,有两种构建方式:
- 懒汉式—线程不安全:最基础的实现方式,线程上下文单例,不需要共享给所有线程,也不需要加synchronize之类的锁,以提高性能。
- 懒汉式—线程安全:加上synchronize之类保证线程安全的基础上的懒汉模式,相对性能很低,大部分时间并不需要同步
- 饿汉方式。指全局的单例实例在类装载时构建。 [2]
- 双检锁式。在懒汉式基础上利用synchronize关键字和volatile关键字确保第一次创建时没有线程间竞争而产生多个实例,仅第一次创建时同步,性能相对较高
- 登记式。作为创建类的全局属性存在,创建类被装载时创建
- 枚举。java中枚举类本身也是一种单例模式
三大要素:
- 私有的构造方法;
- 指向自己实例的私有静态引用;
- 以自己实例为返回值的静态的公有方法。
3.相关实例
①饿汉式单例(线程安全)
阐述:见名知义,“饿汉”说明它很“饥饿”,迫切需要找到吃的,这里也就是我们所说的实例。为什么说它是线程安全的呢?因为我们一开始就创建一个这样的实例,其他线程在访问前这个实例就已经创建完成,在类的生命周期中只创建一次,所以饿汉单例天生就是线程安全的。
1 |
|
输出结果为: true
②懒汉单例(需要加双重检查锁来保证线程安全)
阐述: 所谓懒汉模式,就是像一个“懒汉”一样,需要用到创建实例了程序再去创建实例,不需要创建实例程序就“懒得”去创建实例。为什么说它不是线程安全的呢?因为在高并发的情况下懒汉单例就可能创建多个,这样不仅违背了单例的原则,也会在造成使用不同实例造成的线程安全问题,所以懒汉单例需要加锁。
1 |
|
输出结果为: true
4.总结
懒汉式和饿汉式区别点:
- 饿汉模式是典型的空间换取时间,当类装载的时候就会创建类的实例,不管你用不用,先创建出来,然后每次调用的时候就不需要再判断了,节省了运行时间。但如果一直没有人调用,这种浪费的空间就不值得,特别是在空间不足的情况下。
- 懒汉模式是这是一种时间换空间的做法,要想线程安全,大家第一想到的便是下面这种方式,就是在getSingleton方法加上synchronized关键字,但是这种方式也有致命的缺点,那就是并发率太低。