• sort:Java单例设计终极总结


    概述

    • 单例模式最常见最常问到的设计模式
    • 单例设计模式(Singleton),即某个类在整个系统中只能有一个实例
    • 比如:代表JVM运行环境的Runtime类、代表某类信息的XxxClass、spring-IOC容器bean等
    • 关键点
      • 构造器私有化——保证外部不能随意new出新实例
      • 类自身提供该实例——通过静态变量或者静态方法
    • 设计分类
      • 按实例化时机可分为 饿汉式 和 懒汉式
      • 饿汉式特点是类加载时创建实例对象,不论是否会用到该实例。优点是简单、线程安全,缺点是资源占用。
      • 懒汉式则是延迟实例创建,在需要该类实例时才进行实例化,懒汉式缺点是需要注意线程安全问题。

    饿汉式几种写法

    最经典写法

    public class Eager01 {
    	//构造器私有化
    	private Eager01() {}
    	//public + static,提供外部直接类名获取
    	//final 强调单例
    	public static final Eager01 INSTANCE = new Eager01();
    }
    

    枚举写法

    • 使用枚举的单例设计以及成为现在最为优雅推崇的方式,优点很多
    • 优点:写法简单优雅; 线程安全; 可应对反射攻击; 序列化支持...
    • 唯一缺点:因为枚举类以及继承 Enum, 所以不能再继承拓展。严格的说,这算不上缺点..
    • 写法角度可以视为经典写法的简洁翻版
    //理解:
    //枚举类型即其实例为限定范围的几个,我们只提供一个,那么就是单例
    public enum Eager2_enum {
    	INSTANCE;
    }
    

    静态代码块写法

    • 适用于实例化时需要复杂逻辑处理的场景,比如加载属性文件等
    • 这些实例化处理在静态代码块中完成
    public class Eager3_static_block {
    	private Eager3_static_block() {}
    	public static Eager3_static_block instance;
    	static {
    		//...其他操作,比如资源属性文件加载等
    		instance = new Eager3_static_block();
    	}
    }
    
    • 单例最好加上 final,使用 private staic 方法
    public class Eager3_static_block {
    	private Eager3_static_block() {}
    	public final static Eager3_static_block INSTANCE = init();
    //	static {
    //		//...其他操作,比如资源属性文件加载等
    //		INSTANCE = new Eager3_static_block();
    //	}
    	private static Eager3_static_block init() {
    		return new Eager3_static_block();
    	}
    }
    

    懒汉式几种写法

    简单延迟实例版 - 非线程安全

    public class Lazy01 {
    	//还是一样,构造器私有化
    	private Lazy01() {}
    	//静态私有变量
    	private static Lazy01 instance;
    	//提供public静态方法以获取实例
    	public static Lazy01 getSingleton() {
    		if(null == instance) {
    			instance = new Lazy01();
    		}
    		return instance;
    	}
    }
    

    线程安全 - 静态方法同步版

    public class Lazy2 {
    	//还是一样,构造器私有化
    	private Lazy2() {}
    	//静态私有变量
    	private static Lazy2 instance;
    	//提供public静态方法以获取实例,静态方法加锁
    	public synchronized static Lazy2 getSingleton() {
    		if(null == instance) {
    			instance = new Lazy2();
    		}
    		return instance;
    	}
    }
    

    性能与安全兼顾 - 双重检查同步锁版

    public class Lazy3 {
    	//还是一样,构造器私有化
    	private Lazy3() {}
    	//静态私有变量
    	private static Lazy3 instance;
    	//提供public静态方法以获取实例
    	public static Lazy3 getSingleton() {
    		if(null == instance) { //第一次检查,提高性能,只有第一次为null时才触发锁
    			synchronized (Lazy2.class) {
    				if(null == instance) { //第二次检查,安全考虑,防止线程同时通过第一次检查
    					instance = new Lazy3();
    				}
    			}
    		}
    		return instance;
    	}
    }
    

    优雅懒汉式 - 静态内部类版

    • 同使用枚举的懒汉式一样,属于优雅且受推崇的单例设计
    • 使用静态内部类,内部饿汉式,外部懒汉式,很巧妙,又避免了使用同步锁
    public class Lazy4 {
    	//还是一样,构造器私有化
    	private Lazy4() {}
    	//静态内部类
    	private static class Inner {
    		//饿汉式
    		private static final Lazy4 INSTANCE = new Lazy4();
    	}
    	//外部懒汉式(调用此方法才会加载内部类,创建 INSTANCE 实例)
    	public static Lazy4 getSingleton() {
    		return Inner.INSTANCE;
    	}
    }
    
  • 相关阅读:
    mysql access denied for user root Mysql用户无权限
    远程链接调用sql脚本
    CuteEditor使用详解
    如何设置release模式
    ShardingJDBC不分库,只分表例子
    SpringCloud Stream整合RocketMQ实现消息发送与接收
    Spring Cloud Gateway的PrefixPath及StripPrefix功能
    使用MongoDB的Spring Boot和MongoTemplate教程
    ShardingJDBC读写分离案例
    SpringBoot那些好用的连接池HikariCP
  • 原文地址:https://www.cnblogs.com/noodlerkun/p/11578194.html
Copyright © 2020-2023  润新知