Java设计模式-单例模式(2)

简介: Java设计模式-单例模式(2)

单例模式(Singleton)

定义

某个类只能生成一个实例,该类提供了一个全局访问点供外部获取该实例,其拓展是有限多例模式。

目的

节省内存资源、保证数据内容的一致性,对某些类要求只能创建一个实例,这就是所谓的单例模式。

特点

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

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

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

优点:

在内存里只有一个实例,减少了内存的开销,尤其是频繁的创建和销毁实例。

避免对资源的多重占用(比如写文件操作)。

缺点:

没有接口,不能继承,与单一职责原则冲突,一个类应该只关心内部逻辑,而不关心外面怎么样来实例化。

结构

单例模式的主要角色如下。

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

·访问类:使用单例的类。

注意点

1.单例模式是自关联关系设计。

2.字段 instance 为private,static, volatile修饰。

3.getInstance(全局访问点)为public ,static 修饰,其中涉及了 synchronized关键字的使用 。

  1. 构造函数为private(私有的)。

volatile:

    volatile关键字是为了保证线程安全的,当某个线程对共享变量只是读操作而没有写操作时,使用volatile就可以保证线程安全。volatile的作用是保证可见性和有序性,因为读操作本来就具有原子性,因此仅使用volatile就可以保证线程安全。

synchronized:

    多个线程使用同一个对象进行加锁(基于对象头加锁),可以实现线程间的同步互斥。简单地说,它的原理就是基于对象头加锁,满足原子性、可见性、有序性。

懒汉式(线程安全)

是否 Lazy 初始化:是

是否多线程安全:是

实现难度:易

描述:这种方式具备很好的 lazy loading,能够在多线程中很好的工作,但是,效率很低,99% 情况下不需要同步。
优点:第一次调用才初始化,避免内存浪费。
缺点:必须加锁 synchronized 才能保证单例,但加锁会影响效率。

public class LazySingleton {
//保证 instance 在所有线程中同步
private static volatile LazySingleton instance = null;
private LazySingleton() {
} //private 避免类在外部被实例化

//synchronized 修饰方法级别
public static synchronized LazySingleton getInstance() {
    //getInstance 方法前加同步
    if (instance == null) {
        instance = new LazySingleton();
    }
    return instance;
}

}
懒汉式(线程不安全)

是否 Lazy 初始化:是

是否多线程安全:否

实现难度:易

描述:这种方式是最基本的实现方式,这种实现最大的问题就是不支持多线程。因为没有加锁 synchronized,所以严格意义上它并不算单例模式。

public class LazySingleton {
private static LazySingleton instance;
private LazySingleton (){}
public static LazySingleton getInstance() {
if (instance == null) {
instance = new LazySingleton();
}
return instance;
}
}
饿汉式(线程安全)
是否 Lazy 初始化:否

是否多线程安全:是

实现难度:易

描述:这种方式比较常用,但容易产生垃圾对象。
优点:没有加锁,执行效率会提高。
缺点:类加载时就初始化,浪费内存

public class Singleton {
private static Singleton instance = new Singleton();
private Singleton (){}
public static Singleton getInstance() {
return instance;
}
}
【推荐】双检锁/双重校验锁(DCL,即 double-checked locking)
JDK 版本:JDK1.5 起

是否 Lazy 初始化:是

是否多线程安全:是

实现难度:较复杂

描述:这种方式采用双锁机制,安全且在多线程情况下能保持高性能。getInstance() 的性能对应用程序很关键。

public class Singleton {
private volatile static Singleton singleton;
private Singleton (){}
public static Singleton getSingleton() {
if (singleton == null) {
synchronized (Singleton.class) {
if (singleton == null) {
singleton = new Singleton();
}
}
}
return singleton;
}
}
登记式/静态内部类
是否 Lazy 初始化:是

是否多线程安全:是

实现难度:一般

描述:这种方式能达到双检锁方式一样的功效,但实现更简单。对静态域使用延迟初始化,应使用这种方式而不是双检锁方式。这种方式只适用于静态域的情况,双检锁方式可在实例域需要延迟初始化时使用。调用getInstance()方法时才创建,达到了类似懒汉式的效果,同时又是线程安全的。

public class Singleton {
private static class SingletonHolder {
private static final Singleton INSTANCE = new Singleton();
}
private Singleton (){}
public static final Singleton getInstance() {
return SingletonHolder.INSTANCE;
}
}
枚举
JDK 版本:JDK1.5 起

是否 Lazy 初始化:否

是否多线程安全:是

实现难度:易

优点:线程安全,不用担心反射破坏单例模式,性能高,没有任何锁。

缺点:枚举类占用内存多。

描述:这种实现方式还没有被广泛采用,但这是实现单例模式的最佳方法。它更简洁,自动支持序列化机制,绝对防止多次实例化。

public enum Singleton {
INSTANCE;
public void otherMethod() {
//处理其他功能业务
}
}
23 种设计模式不是孤立存在的,很多模式之间存在一定的关联关系,在大的系统开发中常常同时使用多种设计模式,或者模式与模式之间的组合进行生成更加强大的程序功能。

好了,关于单例模式的说明,馆长就先讲到这里,最近馆长了解到单例模式实现不仅仅是上述的几种,随着软件行业的发展,各种变种也开始流行。由于时间和精力问题,馆长就先整理这些。谢谢各位看官!!
相关文章
|
3月前
|
设计模式 缓存 安全
【Java设计模式 - 创建型模式1】单例模式
【Java设计模式 - 创建型模式1】单例模式
15 0
|
4月前
|
设计模式 Java
Java设计模式【一】:单例模式
Java设计模式【一】:单例模式
42 0
|
4月前
|
设计模式 安全 Java
Java设计模式之单例模式
在软件工程中,单例模式是一种常用的设计模式,其核心目标是确保一个类只有一个实例,并提供一个全局访问点来获取这个实例。Java作为一门广泛使用的编程语言,实现单例模式是面试和实际开发中的常见需求。
81 9
Java设计模式之单例模式
|
设计模式 SpringCloudAlibaba 安全
Java设计模式(二):单例模式
**单例设计模式**(Singleton Design Pattern)理解起来非常简单。一个类只允许创建一个对象(或者实例),那这个类就是一个单例类,这种设计模式就叫作单例设计模式,简称单例模式
123 0
|
设计模式 缓存 安全
单例模式【Java设计模式】
单例模式【Java设计模式】
47 0
|
设计模式 Java Windows
Java设计模式 —— 单例模式
Java设计模式 —— 单例模式
|
设计模式 安全 Java
Java设计模式_单例模式
Java设计模式_单例模式
|
设计模式 安全 Java
Java设计模式—单例模式
Java设计模式—单例模式
74 0
|
设计模式 存储 安全
<Java设计模式>(三)单例模式
<Java设计模式>(三)单例模式
<Java设计模式>(三)单例模式
|
设计模式 缓存 Java
Java设计模式-单例模式
Java设计模式-单例模式