本文摘自《多线程编程实战指南(核心篇)》
单例模式所要实现的目标(效果)非常简单:保持一个类有且仅有一个实例。出于性能的考虑,不少单例模式会采用延迟加载(Lazy Loading)的方式,即仅在需要用到相应实例的时候才创建实例。
单例模式 饿汉模式
1 class SingleThreadSigleton{
2 private static SingleThreadSigleton instance = new SingleThreadSigleton();
3
4 SingleThreadSigleton(){
5 }
6
7 public static SingleThreadSigleton getInstance() {
8 return instance;
9 }
10 }
单线程单例 懒汉模式
1 class SingleThreadSigleton{
2 private static SingleThreadSigleton instance = null;
3
4 private SingleThreadSigleton(){
5 }
6
7 public static SingleThreadSigleton getInstance(){
8 if(null == instance){
9 instance = new SingleThreadSigleton();
10 }
11 return instance;
12 }
13 }
简单加锁实现的单例模式实现
1 class SingleThreadSigleton{
2 private static SingleThreadSigleton instance = null;
3
4 private SingleThreadSigleton(){
5 }
6
7 //静态函数加synchronized相当于synchronized(xxx.class) xxx表示当前类
8 public static synchronized SingleThreadSigleton getInstance(){
9 if(null == instance){
10 instance = new SingleThreadSigleton();
11 }
12 return instance;
13 }
14 }
基于双重检查锁定的错误单例模式实现
1 class SingleThreadSigleton{
2 private static SingleThreadSigleton instance = null;
3
4 private SingleThreadSigleton(){
5 }
6
7 public static SingleThreadSigleton getInstance(){
8 if(null == instance){
9 synchronized (SingleThreadSigleton.class) {
10 if(null == instance) {
11 instance = new SingleThreadSigleton();//操作1
12 }
13 }
14 }
15 return instance;
16 }
17 }
因为需要考虑到重排序的因素,操作1可以分解为一下伪代码所示的几个独立子操作
objRef = allocate(SingleThreadSigleton.class);//分配空间 invokeConstructor(objRef);//初始化objRef引用的对象 instance = objRef;//将对象引用写入共享变量
根据重排序规则2和规则1:临界区内的操作可以在临界区内被重排序。因此上述操作可能被重排序为:子操作① -> 子操作③ -> 子操作②,这就可能导致程序出错。
基于双重检查锁定的正确单例模式实现
1 class SingleThreadSigleton{
2 private volatile static SingleThreadSigleton instance = null;
3
4 private SingleThreadSigleton(){
5 }
6
7 public static SingleThreadSigleton getInstance(){
8 if(null == instance){
9 synchronized (SingleThreadSigleton.class) {
10 if(null == instance) {
11 instance = new SingleThreadSigleton();
12 }
13 }
14 }
15 return instance;
16 }
17 }
基于静态内部类的单例模式实现
1 class SingleThreadSigleton{
2
3 private SingleThreadSigleton(){
4 }
5
6 private static class InstanceHolder{
7 final static SingleThreadSigleton INSTANCE = new SingleThreadSigleton();
8 }
9
10 public static SingleThreadSigleton getInstance() {
11 return InstanceHolder.INSTANCE;
12 }
13 }
基于枚举类型的单例模式实现
1 class EnumBasedSingletonExample{
2 public static void main(String[] args) {
3 new Thread(new Runnable() {
4 @Override
5 public void run() {
6 SingleThreadSigleton.INSTANCE.someService();
7 }
8 }).start();
9 }
10 }
11
12 enum SingleThreadSigleton{
13 INSTANCE;
14 SingleThreadSigleton(){
15 }
16 public void someService(){
17 //doSomething
18 }
19 }