单例模式的特点
1、保证在jvm 中只有一个实例;
2、应用场景:servlet 、springioc(默认单例)、连接池、线程池、枚举、常量;
3、优点: 节省内存,重复使用,方便管理
4、缺点:有线程安全问题;
单例模式的分类
1、懒汉式:将单例对象设为静态属性并加上final修饰符,初始化单例类时就立即创建对象实例,天生线程安全;调用率高
2、饿汉式:将单例对象设为静态属性并加上final修饰符,初始化单例类时不会立即创建对象实例,而是在使用的时候才创建实例,使用懒加载功能;此方式是线程不安全的
3、内部静态类方式:新建一个内部类,将单例对象设为静态属性并加上final修饰符放在内部类里面,真正需要使用的时候才会创建对象实例,
4、枚举式:使用简单,调用率高,因为枚举本身就是单例的,从jvm上就保证了单例,可以避免序列化和反射破坏单例,缺点是没有懒加载功能;枚举一般都是用来保存常量使用的;
5、双重检测锁方式:懒加载方式,只在创建实例时才上锁,获取对象时不上锁;所以使用时只会锁一次;但是此方法会有重排序问题,已不建议使用;
防止反射破坏单例,可以看我的另外一篇文章 https://blog.csdn.net/qq_27184497/article/details/115225855?spm=1001.2014.3001.5501
示例代码
1、饿汉式
- package com.designPatterm.single;
- /**
- * 单例模式--饿汉式
- * 线程安全,效率高
- */
- public class SingletonModelEHan {
-
- private static final SingletonModelEHan obj = new SingletonModelEHan();
-
- // 私有构造方法,防止创建多个实例
- private SingletonModelEHan(){
- // 防止反射破坏单例
- if(null != obj) throw new RuntimeException("单例模式不允许创建多实例");
- }
-
- // 获取实例
- public static SingletonModelEHan getInstance(){
- return obj;
- }
-
- public static void main(String[] args) {
- SingletonModelEHan instance = SingletonModelEHan.getInstance();
- }
- }
2、懒汉式
- package com.designPatterm.single;
-
-
- /**
- * 单例模式--懒汉式
- *
- * 线程安全,效率低
- *
- */
- public class SingletonModelLanHan {
-
-
- private static SingletonModelLanHan obj = null;
-
- // 私有构造方法,防止创建多个实例
- private SingletonModelLanHan(){
- // 防止反射破坏单例
- if(null != obj) throw new RuntimeException("单例模式不允许创建多实例");
- }
-
- // 获取实例,加锁实现线程安全
- public static synchronized SingletonModelLanHan getInstance(){
- if(null == obj){
- obj = new SingletonModelLanHan();
- }
- return obj;
- }
-
- public static void main(String[] args) {
- SingletonModelEHan instance = SingletonModelEHan.getInstance();
- }
- }
3、枚举式
- package com.designPatterm.single;
- /**
- * 单例模式--枚举式
- *
- */
- public class SingletonModelEnum {
-
-
- static enum Single{
- INSTANCE();
- private SingletonModelEnum obj;
- Single(){
- this.obj = new SingletonModelEnum();
- }
-
- public SingletonModelEnum getInstance(){
- return this.obj;
- }
- }
-
- // 私有构造方法,防止创建实例
- private SingletonModelEnum(){
- System.out.println("初始化了");
- }
-
- // 获取实例
- public static SingletonModelEnum getInstance(){
- return SingletonModelEnum.Single.INSTANCE.getInstance();
- }
-
- public static void main(String[] args) {
- SingletonModelEnum instance = SingletonModelEnum.getInstance();
- }
- }
4、内部静态类模式
- package com.designPatterm.single;
- /**
- * 单例模式--内部静态类模式
- *
- */
- public class SingletonModelInnerStatic {
-
-
- static class Single{
- // 内部类实现了延迟加载功能,调用 getInstance() 方法时才会创建实例,
- private static SingletonModelInnerStatic obj = new SingletonModelInnerStatic();
- }
-
- // 私有构造方法,防止创建多个实例
- private SingletonModelInnerStatic(){
- System.out.println("初始化了");
- }
-
- // 获取实例
- public static SingletonModelInnerStatic getInstance(){
- return Single.obj;
- }
-
- public static void main(String[] args) {
- SingletonModelInnerStatic instance = SingletonModelInnerStatic.getInstance();
- }
- }
5、双重检索模式
- package com.designPatterm.single;
- /**
- * 单例模式--双重检索模式
- * 不建议使用,此方法会有重排序问题
- */
- public class SingletonModelDoubleLock {
-
-
- private static SingletonModelDoubleLock obj = null;
-
-
- // 私有构造方法,防止创建多个实例
- private SingletonModelDoubleLock(){
- // 防止反射破坏单例
- if(null != obj) throw new RuntimeException("单例模式不允许创建多实例");
- }
-
- // 获取实例
- public static SingletonModelDoubleLock getInstance(){
- if(null == obj){
- synchronized (SingletonModelDoubleLock.class){
- if(null == obj){
- obj = new SingletonModelDoubleLock();
- }
- }
- }
- return obj;
- }
-
- public static void main(String[] args) {
- SingletonModelDoubleLock instance = SingletonModelDoubleLock.getInstance();
- }
- }