前言

定义

单例模式确保某个类只有一个实例,而且自行实例化并向整个系统提供这个实例。在计算机系统中,线程池、缓存、日志对象、对话框、打印机、显卡的驱动程序对象常被设计成单例。这些应用都或多或少具有资源管理器的功能。

特点

  • 单例类只能有一个实例。
  • 单例类必须自己创建自己的唯一实例。
  • 单例类必须给所有其他对象提供这一实例。

单例模式保证了全局对象的唯一性,比如系统启动读取配置文件就需要单例保证配置的一致性。

实现思路

  • 如果我们要让类在一个虚拟机中只能产生一个对象,我们首先必须将类的构造器的访问权限设置为 private,这样,就不能用 new 操作符在类的外部产生类的对象
  • 但在类内部仍然可以产生该类的对象,

参考链接

实现方式

饿汉式

  • 优点:线程安全,在类加载(ClassLoader)的同时已经创建好了一个静态对象,调用时反应速度快
  • 缺点:对象提前创建,所以会占用一定内存,
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
package com.base.learn;

/**
* 单例涉及模式:饿汉式
*/
public class SingletonTest1 {

public static void main(String[] args) {
Bank bank1 = Bank.getInstance();
Bank bank2 = Bank.getInstance();
System.out.println(bank2 == bank2);
}
}

class Bank {
// 1. 私有化类的构造器
private Bank() {

}

// 2. 内部创建类的对象
// 4. 要求此对象也必须声明为静态的
private static Bank instance = new Bank();

// 3. 提供公共的静态的方法,返回类的对象
public static Bank getInstance() {
return instance;
}
}

懒汉式

  • 优点:”延迟加载”,在需要使用的时候,进行创建,节省内存空间。
  • 缺点:线程不安全,后续学习多线程后,完善下面代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
package com.base.learn;

/**
* 懒汉式
*/
public class SingletonTest2 {
public static void main(String[] args) {
Order order1 = Bank.getInstance();
Order order2 = Bank.getInstance();
System.out.println(order1 == order2);
}
}

class Order {
//1. 私有化类的构造器
private Order() {

}

// 2. 声明当前类对象,没有初始化
// 4. 此对象也必须声明为 static 的
private static Order instance = null;

// 3. 声明 public static 的返回当前类对象的方法
public static Order getInstance() {
if(instance == null){
instance = new Order();
}
return instance;
}
}

懒汉式,线程安全的情况

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
package com.base4_threadsafamore.singleton;

public class SingletonTest3 {
public static void main(String[] args) {

Singleton singleton1 = Singleton.getInstance();
Singleton singleton2 = Singleton.getInstance();

if (singleton1 == singleton2) {
System.out.println("singleton1和singleton2是同一个实例。");
} else {
System.out.println("singleton1和singleton2不是同一个实例。");
}

}
}

class Singleton {
private static volatile Singleton instance; // 使用volatile关键字确保可见性

private Singleton() {
// 私有构造函数,防止外部创建实例
}

public static Singleton getInstance() {
if (instance == null) { // 第一次检查
synchronized (Singleton.class) {
if (instance == null) { // 第二次检查
instance = new Singleton();
}
}
}
return instance;
}
}

注:后续其他场景,等学习到了,再更新……