概念

  • 单例模式是常见的设计模式之一,分为饿汉式和懒汉式。
  • 使用场景:在项目中,频繁使用的全局单一对象。

饿汉式

  • 先创建好单例对象,后使用
  • 优点:写法简单,在类加载时候创建对象,避免了线程同步的问题
  • 缺点:如果后期开发未使用该单例对象,浪费内存
1
2
3
4
5
6
7
8
9
10
11
12
13
14
public class SingleTon {
private static SingleTon instance = new SingleTon();

//创建对象的过程可以使用静态代码块代替
// static {
// instance = new SingleTon();
// }

private SingleTon() {}

public static SingleTon getInstance() {
return instance;
}
}

懒汉式

  • 在第一使用时创建对象(延迟加载)
  • 优点:避免浪费内存
  • 缺点:有可能出现线程不安全的问题(多次创建对象)

线程不安全的

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
public class SingleTon {
private static SingleTon instance;

private SingleTon() {}

public static SingleTon getInstance() {

if (null == instance) {
/*
此处会出现线程安全问题。
出现原因:线程在内存中是以时间片轮转的方式运行,
可能出现多个线程运行到此处。
*/
instance = new SingleTon();
}
return instance;

}

}

同步代码块

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
public class SingleTon {
private static SingleTon instance;

private SingleTon(){}

public static SingleTon getInstance() {
//此处也会出现线程安全问题,原因同上
//解决方法:双重检查(由于内存中存在线程无序执行,无法实现)
if (null == instance) {
synchronized (SingleTon.class) {
instance = new SingleTon();
}
}
return instance;
}
}

同步函数

1
2
3
4
5
6
7
8
9
10
11
12
13
public class SingleTon {
private static SingleTon instance;

private SingleTon(){}

//此种方法可以解决多线程安全问题,但是效率极低(相当于单线程执行)
public static synchronized SingleTon getInstance() {
if (null == instance) {
instance = new SingleTon();
}
return instance;
}
}

利用静态内部类(推荐)

  • 静态内部类在第一次使用的时候进行加载
  • 优点:实现了懒加载的特性,避免了多线程安全问题
1
2
3
4
5
6
7
8
9
10
11
public class SingleTon {
private SingleTon() {}

public static SingleTon getInstance() {
return InstanceBuilder.instance;
}

private static class InstanceBuilder{
private static SingleTon instance = new SingleTon();
}
}