设计模式系列(六)单例模式的五种实现
发布日期:2021-07-23 22:22:39 浏览次数:1 分类:技术文章

本文共 3018 字,大约阅读时间需要 10 分钟。

参考:

对于系统中的某些类来说,只有一个实例很重要,例如,一个系统中可以存在多个打印任务,但是只能有一个正在工作的任务;一个系统只能有一个窗口管理器或文件系统;一个系统只能有一个计时工具或ID(序号)生成器。

单例模式可以使整个系统拥有一个全局的对象,方便资源的共享和系统行为的协调。

一:饿汉式

public class Singleton {       private static Singleton = new Singleton();    private Singleton() {}    public static getSignleton(){        return singleton;    }}

饿汉式是最简单的,在类加载的时候就被创建,也没有多线程的问题,

但是不能满足延迟加载的需求

 

二:懒汉式:

public class Singleton {	//私有静态实例	private static Singleton  singleton;	//构造私有	private Singleton() {}	public void doSomeThing() {	        System.out.println("doSomeThing");	}		 //加锁    public static synchronized Singleton getInstance() {        if (singleton == null) {        	singleton = new Singleton();        }        return singleton;    }}

懒汉式在用的的时候才考虑第一次创建对象,但是这里会有多线程的问题,多以用synchronized给方法加锁,

但是这里每次访问的时候都是synchronized的,性能会有影响,所以有了第三种

 

三:双重检查锁锁(double checked locking)

public class Singleton {	//私有静态实例	private static volatile Singleton  singleton;	//构造私有	private Singleton() {}	public void doSomeThing() {	        System.out.println("doSomeThing");	}		 //加锁    public static  Singleton getInstance() {        if (singleton == null) {        	synchronized (Singleton.class){        		if (singleton==null) {        			singleton = new Singleton();				}        	}        }        return singleton;    }}

这里面解释一下:

1.为什么synchronized内部就还要再检查一次

因为在一个线程进入synchronized内部的时候,另外一个可能进了第一层if了,所以在锁起来的代码内部还要再判断一次

2.为什么要用volatile修饰singleton

volatile关键字可以保证有序性,如果不加这个关键字的话,可能一个线程在synchronized内部new 但还没执行完,另外一个线程得到的实例虽然不为null,但是并没有初始化

singleton = new Singleton()  这条命令执行分为三部分

1.为对象分配内存

2.执行构造方法语句,初始化实例对象

3.把singleton的引用指向分配的内存空间

如果指令重拍为132,则多线程情况下就会有问题!

-------------------------------------------------------------------------------------------------------------------------

上面三种方式是传统的单例模式实现方式

四:静态内部类

public class Singleton {	private Singleton() {}	public void doSomeThing() {	        System.out.println("doSomeThing");	}    public static  Singleton getInstance() {      return SingletonHolder.sInstance;    }        private static class SingletonHolder{    	private static Singleton sInstance = new Singleton();    }}

当外部类被加载时,其金泰内部类不会被加载,只有当调用SIngleton.getInstance()方法时,才会加载SingletonHolder并且初始化其成员变量。而类加载时是线程安全的。这样既保证了延迟加载,也保证了线程安全,同时也简化了代码量。

 

五 枚举单例

参考:

好处:

1.实例的创建线程安全,确保单例

2.防止被反射创建多个实例

3.没有序列化的问题

/** * 使用枚举的单例模式 * * @author yzl * @see [相关类/方法](可选) * @since [产品/模块版本] (可选) */public class EnumSingleton{    private EnumSingleton(){}    public static EnumSingleton getInstance(){        return Singleton.INSTANCE.getInstance();    }        private static enum Singleton{        INSTANCE;                private EnumSingleton singleton;        //JVM会保证此方法绝对只调用一次        private Singleton(){            singleton = new EnumSingleton();        }        public EnumSingleton getInstance(){            return singleton;        }    }}
public static void main(String[] args) {    EnumSingleton obj1 = EnumSingleton.getInstance();    EnumSingleton obj2 = EnumSingleton.getInstance();    //输出结果:obj1==obj2?true    System.out.println("obj1==obj2?" + (obj1==obj2));}

 

转载地址:https://blog.csdn.net/perfectnihil/article/details/91354197 如侵犯您的版权,请留言回复原文章的地址,我们会给您删除此文章,给您带来不便请您谅解!

上一篇:设计模式系列(五)原型模式
下一篇:设计模式系列(四)建造者模式

发表评论

最新留言

感谢大佬
[***.8.128.20]2024年04月02日 19时15分49秒