Singleton——单例模式
什么是单例模式
确保一个类只生成一个实例,并提供一个访问它的全局访问点。
Singleton模式让类负责保存它的唯一实例,这个类可以保证没有其他实例可以被创建,并且提供一个访问该实例的方法
单例模式的角色构成
- Singleton
Singleton角色中有一个返回唯一实例的静态方法,该方法总会返回同一个实例。
示例程序
类的组成表
类名 | 说明 |
---|---|
Singleton | 只生成一个实例 |
SingletonMain | 测试类 |
示例程序类图
Singleton类
Singleton类只会生成一个实例,Singleton类定义了一个静态成员变量singleton,在类被加载时会将singleton初始化为Singleton的实例,初始化行为仅在该类被加载时进行一次。
Singleton类的构造函数使用了private修饰,这是为了禁止从Singleton类外部调用构造函数。如果从Singleton类以外调用构造方法new Singleton(),会出现编译错误,getInstance()方法提供了获取Singleton类唯一实例的入口。
package com.example.singleton;
public class Singleton {
private static Singleton singleton = new Singleton();
private Singleton() {
System.out.println("生成了一个实例");
}
public static Singleton getInstance() {
return singleton;
}
}
SingletonMain类
调用两次getInstance()方法获取Singleton类的实例,通过"=="判断是否为同一个实例。
package com.example.singleton;
public class SingletonMain {
public static void main(String[] args) {
System.out.println("Start");
Singleton obj1 = Singleton.getInstance();
Singleton obj2 = Singleton.getInstance();
if (obj1 == obj2) {
System.out.println("obj1和obj2是相同的实例");
} else {
System.out.println("obj1和obj2是不同的实例");
}
System.out.println("End");
}
}
测试结果
Start
生成了一个实例
obj1和obj2是相同的实例
End
拓展延伸
多线程下的单例模式
在多线程环境下,以下程序(懒汉式单例)在多个线程调用getInstance()方法创建实例时,可能会生成多个实例;
示例程序:
SingletonThread类
package com.example.singleton.test;
public class SingletonThread {
private static SingletonThread singleton = null;
private SingletonThread() {
System.out.println("生成了一个实例");
slowdown();
}
public static SingletonThread getInstance() {
// 线程不安全,使用null == singleton判断实例为空后,生成了一个新的实例
// 在多线程环境下,其他线程也可能判断 if (null == singleton)
if (null == singleton) {
singleton = new SingletonThread();
}
return singleton;
}
private void slowdown() {
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
SingletonThreadMain类
package com.example.singleton.test;
public class SingletonThreadMain extends Thread{
public static void main(String[] args) {
System.out.println("Start.");
new SingletonThreadMain("A").start();
new SingletonThreadMain("B").start();
new SingletonThreadMain("C").start();
System.out.println("End.");
}
public void run() {
SingletonThread obj = SingletonThread.getInstance();
System.out.println(getName() + ": obj = " + obj);
}
public SingletonThreadMain(String name) {
super(name);
}
}
测试结果
Start.
End.
生成了一个实例
生成了一个实例
生成了一个实例
B: obj = com.example.singleton.test.SingletonThread@59e72e28
C: obj = com.example.singleton.test.SingletonThread@4a140fe5
A: obj = com.example.singleton.test.SingletonThread@2f5aff2b
SingletonThread@59e72e28
C: obj = com.example.singleton.test.SingletonThread@4a140fe5
A: obj = com.example.singleton.test.SingletonThread@2f5aff2b