保证一个类仅有一个实例,并提供一个访问它的全局访问点。
要想控制一个类只被创建一个实例,那么首要的问题就是把创建实例的权限收回来,让类自己来负责创建自己类的实例,然后由这个类来提供外部可以访问这个类实例的方法,这就是单例模式的实现方法。
单例模式的结构和实现
Singleton:负责创建Singleton类自己的唯一实例,并提供一个getInstance的方法,来外部来访问这个类的唯一实例。
- 私有化构造方法
- 提供静态的获取实例的方法
- 定义存储实例的属性,因为要在静态方法中使用,因此要加上static修饰
- 实现控制实例的创建
示例代码
懒汉模式
所谓懒汉模式,既然懒,那么在创建对象实例时就不要着急,在马上要使用对象实例时才会创建,在装载对象时不会创建对象实例。
package com.liuhao.designpattern.singleton;
/**
* 单例模式懒汉模式
*
* @author liuhao
*
* 2015年7月17日
*/
public class SingletonLazy {
// 4. 定义一个变量来存储创建好的类实例
// 5. 因为要在静态方法中使用,因此要加上static修饰
private static SingletonLazy instance = null;
// 1. 构造方法私有化,好在内部控制创建实例的数目
private SingletonLazy() {
}
// 2. 定义一个方法为客户端提供类实例
// 3. 这个方法需要定义成类方法,也就是
public static SingletonLazy getInstance() {
// 6. 判断存储实例的变量是否有值
if (instance == null) {
instance = new SingletonLazy();
}
return instance;
}
private String singletonData;// 单例可以有自己的属性
/**
* 获取属性的值
*
* @return 属性的值
*/
public String getSingletonData() {
return singletonData;
}
/**
* 单例可以有自己的操作方法
*/
public void singletonOperation() {
}
}
饿汉模式
所谓饿汉模式,就是在创建对象实例时比较急,在装载类的时候就会创建对象实例。
package com.liuhao.designpattern.singleton;
/**
* 单例模式饿汉模式
*
* @author liuhao
*
* 2015年7月17日
*/
public class SingletonHungry {
// 4. 直装载类的时候就会创建对象实例,只创建一次
private static SingletonHungry instance = new SingletonHungry();
// 1. 构造方法私有化,好在内部控制创建实例的数目
private SingletonHungry() {
}
// 2. 定义一个方法为客户端提供类实例
// 3. 这个方法需要定义成类方法,也就是
public static SingletonHungry getInstance() {
// 5. 直接使用以及创建好的实例
return instance;
}
private String singletonData;// 单例可以有自己的属性
/**
* 获取属性的值
*
* @return 属性的值
*/
public String getSingletonData() {
return singletonData;
}
/**
* 单例可以有自己的操作方法
*/
public void singletonOperation() {
}
}
其他
单例模式的范围
目前Java实现的单例是一个虚拟机范围的,因为装载类的功能是虚拟机的,所以一个虚拟机在通过自己的ClassLoader装载饿汉模式实现单例时就会创建一个类的实例。
因此如果一个虚拟机里面有很多个ClassLoader,而这些ClassLoader都装载某个类的话,就会产生多个实例。
单例模式的调用顺序
- 懒汉模式
- 饿汉模式
体现的一些思想
-
延迟加载
懒汉模式中,一开始没有加载所需的资源或者数据,一直等到马上就要使用了才加载,即所谓的“延迟加载”。 -
缓存
当某些资源或数据被频繁的使用,而且它们是存储在系统外部的(如数据库、硬盘),那么每次操作都要从数据库获取,速度会很慢,操作性能问题。
一个简单的方法就是把这些数据缓存到内存中,每次操作的时候先到内存里找,若有则直接使用;若果没有再获取它并设置到缓存中。
缓存是一种典型的空间换取时间的方案。
线程安全
-
不加同步的懒汉模式是线程不安全的。比如,有线程A、B同时调用getInstance方法,那就可能导致并发问题,如图。
-
如何实现懒汉模式的线程安全
- 加上关键字
synchronized
,如下
public static synchronized SingletonLazy getInstance() {}
- 双重检查加锁。不是在每次进入getInstance时都需要同步,而是先不同步,进入方法后,先检查实例是否存在。如果不存在才进入下面的同步块,这是第一重检查。进入同步块后,再次检查实例是否存在,如果不存在,就在同步的情况下创建一个实例,这是第二重检查。
双重检查加锁机制的实现需要使用volatile
关键字,被它修饰的变量的值将不会被本地线程缓存,所有对该变量的读写都是直接操作共享内存,从而确保多个线程能够正确的处理该变量。
具体实现:
public static SingletonVolatile getInstance() { // 检查实例是否存在,不存在则进入到同步块 if (instance == null) { // 同步块,线程安全地创建实例 synchronized (SingletonVolatile.class) { // 再次检查实例是否存在,不存在则真正的创建实例 if (instance == null) { instance = new SingletonVolatile(); } } } return instance; }
这种实现方式既可以实现线程安全,同时也不会对性能造成太大的影响。
- 加上关键字
-
饿汉模式是线程安全的。
作者:hoxis 链接:https://www.jianshu.com/p/24d2e6d9af3e 來源:简书 著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
相关推荐
深入浅出Singleton,详细掌握单例模式
在Java应用中,单例对象能保证在一个...3、有些像交易所的核心交易引擎,控制着交易流程,如果该类可以创建多个的话,系统完全乱了,只有使用单例模式,才能保证核心交易服务器独立控制整个流程。 CSDN代码的详细解释。
java Singleton单例模式 java Singleton单例模式
设计模式C++学习之单例模式(Singleton)
此示例展示了Qml 的单例模式(类似全局对象,只生成一次实例,可全局使用) surfsky.cnblogs.com
简单的单例模式举例Singleton 分为恶汉式 懒汉式
Singleton模式包含的角色只有一个,就是Singleton。Singleton拥有一个私有构造函数,确保用户无法通过new直接实例化它。除此之外,该模式中包含一个静态私有成员变量instance与静态公有方法Instance()。Instance()...
单例模式(Singleton Pattern)是 Java 中最简单的设计模式之一。这种类型的设计模式属于创建型模式,它提供了一种创建对象的最佳方式。 这种模式涉及到一个单一的类,该类负责创建自己的对象,同时确保只有单个...
单例模式 Singleton 单例模式线程安全问题和拓展
单例设计模式Singleton1
singleton 单例 java 详细介绍了单例模式的使用,很不错的单例模式的介绍
设计模式系列之01-单例模式(Singleton模式),很好的资源,理论实践结合讲述,逐步更新
单例模式(Singleton)的6种实现,单例模式(Singleton)的6种实现
一个产生随机数的例子,整个应用程序中只需要一个类的实例来产生随机数,客户端程序从类中获取这个实例,调用这个实例的方法nextInt(),公用的方法访问需要进行同步,这是单例模式需要解决的同步问题。
singleton单例模式1
IOS 单例设计模式实例Demo 单例 设计 模式 IOS Singleton
c++ singleton单例模式
单例模式(Singleton)
Singleton pattern单例模式应用