定义:

  指一个类只有一个实例,且该类能自行创建这个实例的一种模式.

特点:

  单例类只有一个实例对象;

  该单例对象必须由单例类自行创建;

  单例类对外提供一个访问该单例的全局访问点;

应用场景:

  多线程中的线程池、数据库的连接池、网站的计数器、Web 应用的配置对象、应用程序中的对话框、 系统中的缓存等常常被设计成单例

模式结构:

  1.单例类:包含一个实例且能自行创建这个实例的类

  2.访问类:使用单例的类

实现:

  单例模式的实现通常又分为了6种实现方式

  1.饿汉式

  2.懒汉式(unsafe)

  3.懒汉式(secruity)

  4.懒汉式(Double check)

  5.懒汉式(volatile security)

  6.静态内部类(inner_static)

总述:如果要写一个单例模式,要私有构造函数,对外提供唯一对象实例。

本文共有6种写法,仅供参考(全篇阅读约10分钟)

1.饿汉式

  优点: 在多线程情况下,该方法创建的单例是线程安全的(立即加载)

  缺点: 由于instance 是由静态修饰的,所以在加载类之前就会将instance 加载到方法区中,如果长时间不用,这样会长时间占用内存。

public class HungrySingleton {

    private static HungrySingleton instance = new HungrySingleton();

    private HungrySingleton() {};

    public HungrySingleton getHungrySingleton() {
return instance;
}
}

2.懒汉式(Unsafe)

  优点:只有在使用时才会被创建,不会在初始化时消耗大量内存

  缺点:线程是不安全的。当被多个线程调用时,线程是不安全,需要在获取实例方法添加synchronized

public class LazySingleton {

    private static LazySingleton instance ;
private LazySingleton() {} public LazySingleton getLayzSingleton() {
if(instance == null)
instance = new LazySingleton();
// return instance;
return LazySingleton.instance; ////此种写法更直观,可以看出是某个类的实例变量
}
}

3.懒汉式(security)

  优点:只有在使用时才会被创建,不会在初始化时消耗内存,同时又确保了线程是安全的

  缺点:虽然保证线程是安全,由于加了同步锁会在并发访问时影响性能

public class LazySingletonSecurity {

    private static LazySingletonSecurity instance;

    private LazySingletonSecurity() {}

    public synchronized LazySingletonSecurity getInstance() {
if(instance == null)
instance = new LazySingletonSecurity();
return instance;
// return LazySingletonSecurity.instance;
}
}

4.懒汉式(double check)

  在示例3中,在getInstance()获取实例的方法是同步的,其目的是为了防止多个线程在获取实例时并发的创建多个对象,但是这样影响了访问的效率,既然是为了防止多线程并发访问,那我们可以把同步方法改成同步代码块,在创建instance 实例处加上同步代码块,当线程1访问instance == null;进来拿到同步锁,将实例创建完成才释放锁,当线程2访问时,instance 已经不等于null 直接返回了实例。

  优点:在使用时都会被创建,访问效率高、线程安全

  缺点:可能会实现空指针情况

public class LazySingletonDoubleCheck {

    private static LazySingletonDoubleCheck instance;
private LazySingletonDoubleCheck() {} /**
* synchronized处:当线程1执行完创建实例释放锁后,线程2执行到此处代码时,得到实例不等于null,于是
* 返回拿到了返还的实例,可能这样解释你觉得怎么会出现这种情况,但这种情况确实会出现,是因为java
* 的happens-before规则导致的,在代码编译后,编译器和处理器会进行优化处理,但在在堆内存创建
* 对象后直接返回了,可能还没有将对象的一些属性初始化完成,而线程2得到的实例可能会出现空指针的情况。
*/
public LazySingletonDoubleCheck getInstance() {
if(instance == null) {
synchronized (LazySingletonDoubleCheck.class) {
if (instance == null)
instance = new LazySingletonDoubleCheck();
}
}
return instance;
}
}

5.懒汉式(volatile security)

  优点:在使用时都会被创建,访问效率高、线程安全

  缺点:如果对关键字性能不了解,这种写法可能不太会被接受

    volatile:虽然不能保证原子性,但保证内存的可见性,即多个线程看到的数据是同一份,它在加载读的时候,会保证所有写的操作完成之后,才会去读,即保证了在创建对象的时候会保证对象完全初始化创建完成。

public class LazySingletonVolatileSecurity {

    private static volatile LazySingletonVolatileSecurity instance;

    private LazySingletonVolatileSecurity() {};

    public LazySingletonVolatileSecurity getInstance() {
if (instance == null) {
synchronized (LazySingletonVolatileSecurity.class) {
if(instance == null)
instance = new LazySingletonVolatileSecurity();
}
} return instance;
}
}

6.静态内部类(inner_static)

  优点:

    1.被static 修饰的类,只有使用到时才会进行加载,而且只加载1次

    2.这种方式是通才内部类调用外部类构造函数,同时提供1种对外访问的方法来实现的

  缺点:需要对jvm加载class的时机掌握的比较清楚

public class LazySingletonInnerStatic {

    private LazySingletonInnerStatic() {}

    private static class InnerClass{
private static final LazySingletonInnerStatic instace = new LazySingletonInnerStatic();
} public LazySingletonInnerStatic getInstance() {
return LazySingletonInnerStatic.InnerClass.instace;
}
}

java23种设计模式之二: 单例设计模式(6种写法)的更多相关文章

  1. iOS单例设计模式具体解说(单例设计模式不断完好的过程)

    在iOS中有非常多的设计模式,有一本书<Elements of Reusable Object-Oriented Software>(中文名字为<设计模式>)讲述了23种软件设 ...

  2. iOS开发——高级篇——iOS中常见的设计模式(MVC/单例/委托/观察者)

    关于设计模式这个问题,在网上也找过一些资料,下面是我自己总结的,分享给大家 如果你刚接触设计模式,我们有好消息告诉你!首先,多亏了Cocoa的构建方式,你已经使用了许多的设计模式以及被鼓励的最佳实践. ...

  3. iOS中常见的设计模式(MVC/单例/委托/观察者)

    关于设计模式这个问题,在网上也找过一些资料,下面是我自己总结的,分享给大家 如果你刚接触设计模式,我们有好消息告诉你!首先,多亏了Cocoa的构建方式,你已经使用了许多的设计模式以及被鼓励的最佳实践. ...

  4. java设计模式——单例设计模式

    /*设计模式:对问题行之有效的解决方式.其实它是一种思想. 1,单例设计模式.    解决的问题:就是可以保证一个类在内存中的对象唯一性. 必须对于多个程序使用同一个配置信息对象时,就需要保证该对象的 ...

  5. Java 基础入门随笔(10) JavaSE版——单例设计模式

    设计模式:对问题行之有效的解决方式.其实它是一种思想. 1.单例设计模式. 解决的问题:就是可以保证一个类在内存中的对象唯一性.(单个实例) 使用单例设计模式需求:必须对于多个程序使用同一个配置信息对 ...

  6. Java面试 - 什么是单例设计模式,为什么要使用单例设计模式,如何实现单例设计模式(饿汉式和懒汉式)?

    什么是单例设计模式? 单例设计模式就是一种控制实例化对象个数的设计模式. 为什么要使用单例设计模式? 使用单例设计模式可以节省内存空间,提高性能.因为很多情况下,有些类是不需要重复产生对象的. 如果重 ...

  7. Java单例设计模式的实现

    1. 单例设计模式的定义 单例设计模式确保类只有一个实例对象,类本身负责创建自己的对象并向整个系统提供这个实例.在访问这个对象的时候,访问者可以直接获取到这个唯一对象而不必由访问者进行实例化. 单例设 ...

  8. python之单例设计模式

    设计模式之单例模式 单例设计模式是怎么来的?在面向对象的程序设计中,当业务并发量非常大时,那么就会出现重复创建相同的对象,每创建一个对象就会开辟一块内存空间,而这些对象其实是一模一样的,那么有没有办法 ...

  9. 单例设计模式 --c#

    单例设计模式:在单例设计模式中我们要保持对象始终是唯一的 参考代码: class SingleObject { private SingleObject() { } private static Si ...

随机推荐

  1. git别名

    git config --global alias.lg 'log --oneline --all --graph --decorate'

  2. 出现 Request Entity Too Large问题的解决方法

    根据经验判断应该是上传文件大小被限制了,检查了应用配置是10M,把它设置成100M,重启服务也不能解决问题. 原来我们的tomcat是通过nginx发现服务代理的,问题就出现nginx服务器上,原来n ...

  3. mysql监控优化(一)连接数和缓存

    一.mysql的连接数 MYSQL数据库安装完成后,默认最大连接数是100,一般流量稍微大一点的论坛或网站这个连接数是远远不够的,连接数少的话,在大并发下连接数会不够用,会有很多线程在等待其他连接释放 ...

  4. Vi文本编辑

    vi 有3种工作模式,分别是命令行模式.插入模式.底行模式 . 命令行模式:最初进入的一般模式,该模式下可以移动光标进行浏览,整行删除,但无法编辑文字.插入模式:只有在该模式下,用户才能进行文字的编辑 ...

  5. Yii2 教程 - yii2-redis 扩展详解

    该教程已被合并到<Yii2 权威指南中文版>中!Yiichina 教程地址为<yii2-redis 扩展详解>! 一.简介 yii2-redis 扩展为 Yii2 框架提供了 ...

  6. sublime2常用设置

    设置文本字体格式 • Preferences -> Setting-User • 加入设置:"font_face" : "courier new", &q ...

  7. 页面优化——减少HTTP请求数

    1.关于减少http请求数 关于减少http请求数,是前端开发性能优化的一个非常重要方面,所以在基本所有的优化原则里,都有这一条原则:减少http请求数. 先不考虑其他的,我们先考虑为什么减少http ...

  8. PKU 3318 Matrix Multiplication(随机化算法||状态压缩)

    题目大意:原题链接 给定三个n*n的矩阵A,B,C,验证A*B=C是否成立. 所有解法中因为只测试一组数据,因此没有使用memset清零 Hint中给的傻乎乎的TLE版本: #include<c ...

  9. The 15th UESTC Programming Contest Preliminary M - Minimum C0st cdoj1557

    地址:http://acm.uestc.edu.cn/#/problem/show/1557 题目: Minimum C0st Time Limit: 3000/1000MS (Java/Others ...

  10. hihocoder1478 水陆距离

    地址:http://hihocoder.com/problemset/problem/1478 题目: 水陆距离 时间限制:10000ms 单点时限:1000ms 内存限制:256MB 描述 给定一个 ...