0%

单例模式

前言:单例模式

懒汉式单例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
/**
* @author shency
* @description: 懒汉式单例,线程不安全
*/
public class Singleton {
private Singleton(){}
private static Singleton instance = null;
public static Singleton getInstance(){
if(instance == null){
instance = new Singleton();
}
return instance;
}
}

加入synchronized

1
2
3
4
5
6
7
8
9
10
11
12
13
14
/**
* @author shency
* @description: 懒汉式单例,线程安全
*/
public class Singleton {
private Singleton(){}
private static Singleton instance = null;
public static synchronized Singleton getInstance(){
if(instance == null){
instance = new Singleton();
}
return instance;
}
}

虽然线程安全,但是效率低,毕竟大多数情况是不需要同步的

使用双重检查锁定

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
/**
* @author shency
* @description: 懒汉式单例,线程安全
*/
public class Singleton {
private Singleton(){}
private static volatile Singleton instance = null;
public static Singleton getInstance(){
if(instance == null){
synchronized(Singleton.class){
if(instance == null){
instance = new Singleton();
}
}
}
return instance;
}
}

注意,双重检查锁定要volatile,因为Java中看似顺序的代码到JVM中会指令重排,Java指令中创建对象和赋值操作是分开进行的,也就是说instance = new Singleton();语句是分两步执行的。但是JVM并不保证这两个操作的先后顺序,也就是说有可能JVM会为新的Singleton实例分配空间,然后直接赋值给instance成员,然后再去初始化这个Singleton实例。这样就使出错成为了可能

容器实现单例模式

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
/**
* @author shency
* @description: 懒汉式单例,容器实现
*/
public class Singleton {
private static Map<String, Object> singletonMap = new HashMap<String, Object>();

private Singleton() {
}

public static void registerSingleton(String key, Object instance) {
if (!singletonMap.containsKey(key)) {
singletonMap.put(key, instance);
}
}

public static Object getSingleton(String key) {
return singletonMap.get(key);
}
}

饿汉式单例

1
2
3
4
5
6
7
8
9
10
11
/**
* @author shency
* @description: 饿汉式单例,线程安全
*/
public class Singleton {
private Singleton(){}
private static Singleton instance = new Singleton();
public static Singleton getInstance(){
return instance;
}
}

饿汉式单例类线程安全控制烦琐,而且性能受影响

饿汉式单例类不能实现延迟加载,不管将来用不用始终占据内存

延迟加载单例模式(静态内部类)

基于饿汉式单例,静态变量在类加载时初始化,而静态内部类在外部类调用时才初始化,因此可使用静态内部类实现延迟加载

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
/**
* @author shency
* @description: 饿汉式单例,线程安全
*/
public class Singleton {
private Singleton() {
}

private static class HolderClass {
private final static Singleton instance = new Singleton();
}

public static Singleton getInstance() {
return HolderClass.instance;
}
}
-------------本文结束感谢您的阅读-------------