创建篇-单例模式
Posted zhixuChen333
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了创建篇-单例模式相关的知识,希望对你有一定的参考价值。
文章目录
前言
单例模式(Singleton)是一种非常简单且容易理解的设计模式。顾名思义,单例即单一的实例,确切地讲就是指在某个系统中只存在一个实例,同时提供集中、统一的访问接口,以使系统行为保持协调一致。singleton一词在逻辑学中指“有且仅有一个元素的集合”,这非常恰当地概括了单例的概念,也就是“一个类仅有一个实例”。
提示:以下是本篇文章正文内容,下面案例可供参考
一、饿汉式
这就是“饿汉模式”(eager initialization),即在初始阶段就主动进行实例化,并时刻保持一种渴求的状态,无论此单例是否有人使用。
public class Singleton2
private static final Singleton2 instance = new Singleton2();
private Singleton2()
public static Singleton2 getInstance()
return instance;
要点:
- 构造方法私有,这样实例化工作完全归属于内部事务,任何外部类都无权干预。
- 实例私有,确保实例的私有性、不可见性和不可访问性。
- "static"关键字保证实例在类加载的时候就初始化,不会被GC回收。
- "final"关键字保证实例是个常量,一旦赋值后不能被修改。
二、懒汉式
1.有缺陷的懒汉式
如代码所示,只有在某线程第一次调用getInstance()方法时才会运行对该类进行实例化的逻辑代码,之后再请求就直接返回此实例了。这样的好处是如无请求就不实例化,节省了内存空间。这样的程序逻辑看似没问题,但其实在多线程模式下是有缺陷的。试想如果是并发请求的话,程序判空逻辑就会同时成立,这样就会多次实例化,并且对instance进行多次赋值(覆盖)操作,这违背了单例的理念。
public class Singleton1
private static Singleton1 instance;
private Singleton1()
public static Singleton1 getInstance()
if (instance == null)
instance = new Singleton1();
return instance;
2.改进后的懒汉式
大家注意到没有,我们一共用了2个嵌套的判空逻辑,这就是懒加载模式的“双检锁”:外层放宽入口,保证线程并发的高效性;内层加锁同步,保证实例化的单次运行。如此里应外合,不仅达到了单例模式的效果,还完美地保证了构建过程的运行效率,一举两得。
public class Singleton3
private static Singleton3 instance;
private Singleton3()
public static Singleton3 getInstance()
if (instance == null)
synchronized (Singleton3.class)
if (instance == null)
instance = new Singleton3();
return instance;
要点:
- “synchronized”关键字,不添加在方法上而是锁同步代码块,减小锁的粒度,提高效率。
总结
提示:这里对文章进行总结:
- 相比“懒汉模式”,其实在大多数情况下我们通常会更多地使用“饿汉模式”,原因在于这个单例迟早是要被实例化占用内存的,延迟懒加载的意义并不大,加锁解锁反而是一种资源浪费,同步更是会降低CPU的利用率,使用不当的话反而会带来不必要的风险。越简单的包容性越强,而越复杂的反而越容易出错、
- 除了“饿汉”与“懒汉”这2种单例模式,其实还有其他的实现方式。但万变不离其宗,它们统统都是由这2种模式发展、衍生而来的。我们都知道Spring框架中的IoC容器很好地帮我们托管了业务对象,如此我们就不必再亲自动手去实例化这些对象了,而在默认情况下我们使用的正是框架提供的“单例模式”。
以上是关于创建篇-单例模式的主要内容,如果未能解决你的问题,请参考以下文章
从零开始学习Java设计模式 | 创建型模式篇:单例设计模式