其实大家看到这个标题还是有点蒙的,六大战将是什么鬼,你怎么不说是四大天王呢,你咋不上天呢。(汗。。)其实六大战将就是六种实现方式了,因为最近在看部网络水文,其中就讲到欧洲第一杀手“皇帝”和他的八大战将,所以就想到了六大战将了,哈哈哈,我真乃人才也。。(还要不要脸。。)
战将一:伯爵(懒汉式-线程不安全)
这种方式是最基本的实现方式,这种实现最大的问题就是不支持多线程。因为没有加锁 synchronized,所以严格意义上它并不算单例模式。这种方式 lazy loading(延迟加载) 很明显,不要求线程安全,在多线程不能正常工作。
/**
- 懒汉式加载-线程不安全
*/
public class SingletonBeanLazyDg {
private SingletonBeanLazyDg(){}
private static SingletonBeanLazyDg singletonBeanLazyDg;
public static SingletonBeanLazyDg getInstance(){
if(singletonBeanLazyDg == null){
singletonBeanLazyDg = new SingletonBeanLazyDg();
}
return singletonBeanLazyDg;
}
public void draw(){
System.out.println(“lazy-singleton-dangerous”);
}
}
战将二:耶稣(懒汉式-线程安全)
这种方式具备很好的 lazy loading(延迟加载),能够在多线程中很好的工作,但是,效率很低,99% 情况下不需要同步。
/**
- 懒汉式加载-线程安全
*/
public class SingletonBeanLazy {
private SingletonBeanLazy (){}
private static SingletonBeanLazy singletonBeanLazy;
public static synchronized SingletonBeanLazy getInstance(){
if(singletonBeanLazy==null){
singletonBeanLazy = new SingletonBeanLazy();
}
return singletonBeanLazy;
}
public void draw(){
System.out.println(“lazy-singleton”);
}
}
战将三:野兽(饿汉模式)
这种方式没有加锁,执行效率会提高。但是类加载时就初始化,容易产生垃圾对象,浪费内存。 它基于 classloader 机制避免了多线程的同步问题,不过,instance 在类装载时就实例化,虽然导致类装载的原因有很多种,在单例模式中大多数都是调用 getInstance 方法, 但是也不能确定有其他的方式(或者其他的静态方法)导致类装载,这时候初始化 instance 显然没有达到 lazy loading (延迟加载)的效果。
/**
- 饿汉式
*/
public class SingletonBeanHunger {
private SingletonBeanHunger(){}
private static SingletonBeanHunger singletonBeanHunger = new SingletonBeanHunger();
public static SingletonBeanHunger getInstance(){
return singletonBeanHunger;
}
public void draw(){
System.out.println(“hunger-singleton”);
}
}
战将四:鬼影(双检锁/双重校验锁(DCL,即 double-checked locking))
这种方式采用双锁机制,安全且在多线程情况下能保持高性能。
/**
- 双重校验锁/双检锁
*/
public class SingletonBeanDCL {
private SingletonBeanDCL(){}
private static volatile SingletonBeanDCL singletonBeanDCL;
public static SingletonBeanDCL getInstance(){
if(singletonBeanDCL==null){
synchronized (SingletonBeanDCL.class){
if (singletonBeanDCL == null){
singletonBeanDCL = new SingletonBeanDCL();
}
}
}
return singletonBeanDCL;
}
public void draw(){
System.out.println(“DCL-singleton”);
}
}
战将五:金童(登记式/静态内部类)
这种方式能达到双检锁方式一样的功效,但实现更简单。对静态域使用延迟初始化,应使用这种方式而不是双检锁方式。这种方式只适用于静态域的情况,双检锁方式可在实例域需要延迟初始化时使用。
/**
- 登记式/静态内部类
*/
public class SingletonBeanStatic {
private SingletonBeanStatic(){}
private static class SingletonBeanHolder{
private static final SingletonBeanStatic SINGLETON_BEAN_STATIC = new SingletonBeanStatic();
}
public static final SingletonBeanStatic getInstance(){
return SingletonBeanHolder.SINGLETON_BEAN_STATIC;
}
public void draw(){
System.out.println(“登记式/静态内部类”);
}
}
战将六:玉女(枚举)
虽然没被广泛应用,但是这是实现单例模式的最佳方法。它更简洁,自动支持序列化机制,绝对防止多次实例化。 这种方式是 Effective Java 作者 Josh Bloch 提倡的方式,它不仅能避免多线程同步问题,而且还自动支持序列化机制,防止反序列化重新创建新的对象,绝对防止多次实例化。
/**
- 枚举
*/
public enum SingletonBeanEnum {
INSTANCE;
public void draw(){
System.out.println(“枚举式单例”);
}
最后
Java架构学习技术内容包含有:Spring,Dubbo,MyBatis, RPC, 源码分析,高并发、高性能、分布式,性能优化,微服务 高级架构开发等等。
还有Java核心知识点+全套架构师学习资料和视频+一线大厂面试宝典+面试简历模板可以领取+阿里美团网易腾讯小米爱奇艺快手哔哩哔哩面试题+Spring源码合集+Java架构实战电子书+2021年最新大厂面试题。
NSTANCE;
public void draw(){
System.out.println(“枚举式单例”);
}
最后
Java架构学习技术内容包含有:Spring,Dubbo,MyBatis, RPC, 源码分析,高并发、高性能、分布式,性能优化,微服务 高级架构开发等等。
还有Java核心知识点+全套架构师学习资料和视频+一线大厂面试宝典+面试简历模板可以领取+阿里美团网易腾讯小米爱奇艺快手哔哩哔哩面试题+Spring源码合集+Java架构实战电子书+2021年最新大厂面试题。
[外链图片转存中…(img-F0ql9EsK-1714799962767)]