单例模式应用于一个类只有一个实例的情况,并且为其实例提供一个全局的访问点。
- 特点:
-
一个类只有一个实例
-
自己创建这个实例
-
整个系统只能用这个实例
- 应用场景
外部资源:每台计算机有若干个打印机,但只能有一个PrinterSpooler,以避免两个打印作业同时输出到打印机。
内部资源:大多数软件都有一个(或多个)属性文件存放系统配置,这样的系统应该有一个对象管理这些属性文件。
1. 饿汉式:单例实例在类装载(ClassLoader)时就构建,急切初始化。(预先加载法)
class Singleton {
//1,私有构造函数
private Singleton(){}
//2,创建本类对象
private static Singleton s = new Singleton();
//3,对外提供公共的访问方法,此处只需要get方法,不需要set方法来修改值
public static Singleton getInstance() { //获取实例
return s;
}
}
- 优点 :
1.线程安全
2.在类加载的同时已经创建好一个静态对象,调用时反应速度快 - 缺点 :
资源效率不高,可能getInstance()永远不会执行到,但执行该类的其他静态方法或者加载了该类(class.forName),那么这个实例仍然初始化
2. 懒汉式:单例实例在第一次被使用时构建,延迟初始化。
//懒汉式,单例的延迟加载模式:使用时再new对象
class Singleton {
//1,私有构造函数
private Singleton(){}
//2,声明一个本类的引用,不创建对象
private static Singleton s;
//3,对外提供公共的访问方法
public static Singleton getInstance() {
if(s == null)
//线程1等待,线程2等待,苏醒后都会创建对象,即>=1
s = new Singleton();
return s;
}
}
/*
* 饿汉式和懒汉式的区别
* 1,饿汉式是空间换时间,懒汉式是时间换空间
* 2,在多线程访问时,饿汉式不会创建多个对象,而懒汉式有可能会创建多个对象
*/
懒汉式在单个线程中没有问题,但在多线程就可能会出现两个或多个Singleton2实例情况,虽然后面实例化的Singleton2会覆盖前面实例化的Singleton2,但最好避免这样的情况。
- 改进方式就是加锁synchornized:双重检测
public class Singleton {
private volatile static Singleton uniqueInstance;
//使用 volatile 可以禁止 JVM 的指令重排,保证在多线程环境下也能正常运行。
//指令重排在单线程环境下不会出现问题,但是在多线程环境下会导致一个线程获得 还没有初始化的实例。
private Singleton() {
}
public static Singleton getUniqueInstance() {
if (uniqueInstance == null) {//第一个 if 语句用来避免 uniqueInstance 已经被实例化之后的加锁操作
synchronized (Singleton.class) {//静态,同步用.class字节码文件
if (uniqueInstance == null) {//第二个 if 语句进行了加锁,所以只能有一个线程进入,就不会出现 uniqueInstance == null 时两个线程同时进行实例化操作。
uniqueInstance = new Singleton();
}
}
}
return uniqueInstance;
}
}
- 优点:
资源利用率高,不执行getInstance()就不会被实例,可以执行该类的其他静态方法 - 缺点:
第一次加载时不够快,多线程使用不必要的同步开销大
3.静态内部类
class Singleton5 {
private Singleton5() {
}
private static class SingletonHelp {
static Singleton5 instance = new Singleton5();
}
public static Singleton5 getInstance() {
return SingletonHelp.instance;
}
}
- 优点:
资源利用率高,不执行getInstance()不被实例,可以执行该类其他静态方法 - 缺点:
第一次加载时反应不够快
本文深入解析单例模式的实现方式,包括饿汉式、懒汉式及静态内部类等,探讨其优缺点,并通过代码示例说明如何在多线程环境中确保线程安全。

141

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



