单例模式的正确使用姿势

在java中单例模式是非常棒的设计模式之一,非常简单,但是同时非常的实用,我在安卓开发的过程当中,就用到过很多次。但是你真的会书写正确的单例吗,在不同的场合可以书写不同的单例,对于开发者来说是很重要的,那么,让我们来看看吧。
最原始的单例:

1
2
3
4
5
6
7
8
9
10
11
class HotelBusProcessor{
private static HotelBusProcessor instance = null;
private HotelBusProcessor(){
}
public static HotelBusProcessor getInstance(){
if(instance==null) instance = new HotelBusProcessor();//这里在多线程的时候可能会出现前一线程正在初始化,后一线程仍然判断为null的状况
return instance;
}
}

正确写法
写法一:

1
2
3
4
5
6
7
8
9
class HotelBusProcessor{
private static HotelBusProcessor instance = new HotelBusProcessor();
private HotelBusProcessor(){
}
public static HotelBusProcessor getInstance(){
return instance;
}
}

此种单例模式可以有效保证只初始化一次,但是每次加载类的时候都会初始化,虽然解决了多线程问题,但对内存有不必要的消耗。
写法二:

1
2
3
4
5
6
7
8
9
10
11
12
class HotelBusProcessor{
private HotelBusProcessor(){
}
private static class singleInstanceHolder{
private static HotelBusProcessor instance = new HotelBusProcessor();
}
public static HotelBusProcessor getInstance(){
return singleInstanceHolder.instance;
}
}

此种单例模式可以有效保证只初始化一次,且每次加载类的时候不会初始化,既解决了多线程问题,同事对内存没有不必要的消耗。
写法三:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
class HotelBusProcessor{
private static volatile HotelBusProcessor instance = null;
private HotelBusProcessor(){
}
public static HotelBusProcessor getInstance(){
if(instance==null){
synchronized(HotelBusProcessor.class){//整个类锁住
//这里在多线程的时候可能会出现前一线程正在初始化,后一线程仍然判断为null的状况
if(instance==null) instance = new HotelBusProcessor();
}
}
return instance;
}
}

此种单例模式可以有效保证只初始化一次,且每次加载类的时候不会初始化,既解决了多线程问题,同事对内存没有不必要的消耗。