单例模式
来源:互联网 发布:node.js实战 pdf 下载 编辑:程序博客网 时间:2024/06/08 01:48
什么是单例模式?
单例模式,就是保证一个类在程序中只有唯一的一个实例。
单例模式的应用场景?
使用单例模式设计的类,一般充当资源管理器的角色,防止多个线程对共享资源的多重占用。又或者是需要频繁创建、销毁对象的类,设计为单例模式可以减少系统消耗,提高系统性能。比如说数据库连接池和多线程线程池就采用了单例设计模式,还有网页的计时器等。
怎么创建一个单例?
首先我们要解决以下问题:
- 类只能被实例化一次
- 类的唯一实例能被其他对象获取
我们把类的实例化交给类自己去完成,用 private 修饰构造函数,在类外部就不能通过 new 实例化新的对象了,这就解决了第一个问题;然后提供一个公共的静态方法 getInstance() 来获取类的唯一实例,这就解决了第二个问题。
创建单例的方法一般有:懒汉式、饿汉式、静态内部类
- 懒汉式(双重检验锁)
只有当对象第一次被调用时才创建实例。
public class Singleton{ private volatile static Singleton instance; private Singleton(){} // 简单地把getInstance()方法设为synchronized也能保证线程安全,但不高效 public static Singleton getInstance(){ if(instance == null){ // 第一次检验实例是否已创建 synchronized(Singleton.class){ if(instance == null){ // 第二次检验防止第一次也检验到null的另一个线程获得锁后又创建第二个实例 instance = new Singleton(); } } } return instance; }}
把 instance 声明为 volatile 是因为 new Singleton() 语句不是原子操作,JVM会进行以下三个操作
- 为 instance 分配内存
- 调用构造函数来初始化成员变量
- 将 instance对象 指向分配的内存空间
但即时编译器的指令优化不保证 2 和 3 的执行顺序,可能导致按 1-3-2 的顺序执行时,线程一执行完 3 就被线程二抢占,此时 instance 虽然不为 null 却还没初始化。
- 饿汉式(static final filed)
类加载时就初始化 instance 实例。
public class Singleton{ private static final instance = new Singleton(); private Singleton(){} public static Singleton getInstance(){ return instance; }}
这个方法非常简单方便,单例一开始就初始化为final,保证了线程安全。但这不是懒加载模式,即使 getInstance() 从没被调用过,单例也会在类加载时就被初始化。饿汉式不适用于 Singleton 实例的创建需要依赖参数或配置文件的场景。
- 静态内部类(static nested class)
在 Singleton 内声明一个静态的内部类,让内部类持有 Singleton 单例。
public class Singleton { private static class SingletonHolder { private static final Singleton INSTANCE = new Singleton(); } private Singleton (){} public static final Singleton getInstance() { return SingletonHolder.INSTANCE; } }
当 getInstance() 方法被调用时,内部类 SingletonHolder 才被加载,然后初始化 INSTANCE 单例,因此是懒汉式,且线程安全的。
总结
一般情况下使用 饿汉式 就好,如果需要懒加载就用使用 静态内部类 的方法吧。
- 单例、单例模式
- 单例模式-多线程单例模式
- 单件模式(单例模式)
- 设计模式------单例模式
- 设计模式------单例模式
- 设计模式-单例模式
- 设计模式 - 单例模式
- 设计模式---单例模式
- 设计模式---单例模式
- PHP模式-单例模式
- 【设计模式】单例模式
- 设计模式-单例模式
- 设计模式----单例模式
- 设计模式--单例模式
- 设计模式-单例模式
- 单例模式(单子模式)
- 设计模式-单例模式
- [设计模式] 单例模式
- String类总结之内存分析
- NYIST-2017大一新生第二次周赛题解
- TCP协议中的序列号
- ThreadLocal学习
- 倍增源代码
- 单例模式
- Binary Search:240. Search a 2D Matrix II
- 什么是dubbo
- apt-get指令的autoclean,clean,autoremove的区别
- Callable和Future
- 整数分解为若干项之和(20 分)
- JavaWeb九大内置对象之request
- MySql数据库-02DDL语言(上)之操作数据库
- 手机灭屏,js定时器停止计算