1.饿汉单例模式
在装载该单例类的时候就会创建类实例,实例代码如下所示:
public class Singleton {
private static Singleton instance = new Singleton();
private Singleton() {
}
public static Singleton getInstance() {
return instance;
}
}
2.懒汉单例模式
(延迟加载思想)这一思想的核心在于直到需要使用某些资源或数据时再去加载该资源或获取该数据,这样可以尽可能地节省使用前的内存空间,一般推荐的单例模式都是懒汉模式。
public class Singleton {
private static Singleton instance = null;
private Singleton() {
}
public static Singleton getInstance() {
// 如果instance未被初始化,则初始化该类实例
if (instance == null) {
instance = new Singleton();
}
return instance;
}
}
3.线程安全的懒汉单例模式
public class Singleton {
private static Singleton instance = null;
private Singleton() {
}
public static synchronized Singleton getInstance() {
// 如果instance未被初始化,则初始化该类实例
if (instance == null) {
instance = new Singleton();
}
return instance;
}
}
4.双重检查加锁单例模式
线程安全的懒汉单利模式:(双重检查加锁机制):在程序每次调用getInstance()方法时先不进行同步,而是在进入该方法后再去检查类实例是否存在,若不存在则进入接下来的同步代码块;进入同步代码块后将再次检查类实例是否存在,若不存在则创建一个新的实例,这样一来,就只需要在类实例初始化时进行一次同步判断即可,而非每次调用getInstance()方法时都进行同步判断,大大节省了时间。
public class Singleton {
/**
* 装载时不创建类实例,但需要利用一个类变量去保存后续创建的类实例 添加volatile关键词使其不会被
* 本地线程缓存,保证线程能正确处理添加static关键词使得该变量能在getInstance()静态方法中使用
*/
private volatile static Singleton instance = null;
private Singleton() {
}
public static Singleton getInstance() {
// 第一重检查:如果instance未被初始化,则进入同步代码块
if (instance == null) {
// 同步代码块,保证线程安全
synchronized (Singleton.class) {
// 第二重检查:如果instance未被初始化,则初始化该类实例
if (instance == null) {
instance = new Singleton();
}
}
}
return instance;
}
}
5.单例模式的最佳实现一
public class Singleton {
/**
* 类级内部类,用于缓存类实例 该类将在被调用时才会被装载,从而实现了延迟加载
* 同时由于instance采用静态初始化的方式,因此JVM能保证其线程安全性
*/
private static class Instance {
private static Singleton instance = new Singleton();
}
/**
* 私有化构造方法,使外部无法通过构造方法构造除instance外的类实例 从而达到单例模式控制类实例数目的目的
*/
private Singleton() {
}
/**
* 类实例的全局访问方法 添加static关键词使得外部可以通过类名直接调用该方法获取类实例
*
* @return 单例类实例
*/
public static Singleton getInstance() {
return Instance.instance;
}
}
6.单例模式的最佳实现二
- 枚举类实现其实省略了
private类型的构造函数 - 枚举类的域(field)其实是相应的enum类型的一个实例对象
public enum Singleton {
INSTANCE;
}
完整的枚举类型单例代码如下所示:
package com.mall.concurrcy.singleton;
import com.mall.concurrcy.annotations.Recommend;
import com.mall.concurrcy.annotations.ThreadSafe;
/**
* 枚举模式:最安全的
*/
@ThreadSafe
@Recommend
public class SingleTon7 {
//私有构造方法
private SingleTon7(){
}
//静态工厂方法
public static SingleTon7 getInstance(){
return SingleTon.INSTANCE.getSingleTon();
}
private enum SingleTon{
INSTANCE;
private SingleTon7 singleTon;
//JVM保证这个方法只调用一次
SingleTon(){
singleTon = new SingleTon7();
}
public SingleTon7 getSingleTon(){
return singleTon;
}
}
}
7.多利模式的简介
既然有单例模式,会不会有双例模式、三例模式等。实例代码如下所示:
public class Singleton {
// 可创建的最大类实例数,这里以“双例模式”为例
private static final int MAX = 2;
// 类实例缓存KEY值
private static final String KEY = "CACHE";
// 当前正在使用的实例序号
private static int index = 1;
// 类实例缓存容器
private static Map<String, Singleton> map = new HashMap<>();
/**
* 私有化构造方法,使外部无法通过构造方法构造除instance外的类实例 从而达到单例模式控制类实例数目的目的
*/
private Singleton() {
}
/**
* 类实例的全局访问方法 添加static关键词使得外部可以通过类名直接调用该方法获取类实例
*
* @return 单例类实例
*/
public static Singleton getInstance() {
// 尝试从缓存容器中获取第index个类实例
String key = KEY + index;
Singleton instance = map.get(key);
// 未能获取类实例,则初始化该实例,并将其缓存至容器相应index中
if (instance == null) {
instance = new Singleton();
map.put(key, instance);
}
// 这里以最基本的顺序调用为例,其他复杂调度方式不加讨论,具体调用方式如下
// index++,以在下一次调用中获取下一个类实例,当达到类实例数上限时,重新获取第一个类实例
if ((++index) > MAX) {
index = 1;
}
return instance;
}
}
本文探讨了单例模式的多种实现方式,包括饿汉单例、懒汉单例、线程安全的懒汉单例以及双重检查加锁单例模式,并详细解析了这些模式的工作原理和优缺点。最后,文章提到了单例模式的最佳实践,包括使用枚举类实现单例,以及对多利模式的简介,引发对多实例模式的思考。
1383

被折叠的 条评论
为什么被折叠?



