Java中的单例模式
- 多线程中可能会导致对象的多次初始化.
懒汉式的实现
- 之所以成为懒汉,个人认为应该是类的初始化只在需要的时候进行,所以很"懒".
线程不安全
/*懒汉 非线程安全*/
public class SingleTon_01 {
private static SingleTon_01 singleTon_01 = null;
private SingleTon_01() {
}
public static SingleTon_01 getSingleTon_01() {
if (singleTon_01 == null) {
singleTon_01 = new SingleTon_01();
}
return singleTon_01;
}
public void print() {
System.out.println("singleton_01");
}
}
线程安全
/*懒汉 线程安全*/
public class SingleTon_02 {
private static SingleTon_02 singleTon_02 = null;
private SingleTon_02() {}
private static synchronized SingleTon_02 getSingleTon_02() {
if (singleTon_02 == null) {
singleTon_02 = new SingleTon_02();
}
return singleTon_02;
}
}
饿汉实现
-
在类加载时就进行初始化,可能会产生垃圾对象,但是不会有多线程的问题出现.
/*饿汉式*/ public class SingleTon_03 { private static SingleTon_03 singleTon_03 = new SingleTon_03(); private SingleTon_03() { } public static SingleTon_03 getSingleTon_03() { return singleTon_03; } }
双重校验锁模式
- 要注意变量需要添加volatile关键字.
-
假设有两个进程分别调用了getInstance方法,进程A首先将变量复制到CPU0缓存当中,进行初始化操作,如果没有volatile关键字,那么进程B在调用此方法时复制到CPU1缓存中的可能是未被更新的null,此时问题就出现了.
/*双重校验锁模式*/ public class SingleTon_04 { private static volatile SingleTon_04 singleTon_04 = null; private SingleTon_04() { } public static SingleTon_04 getSingleTon_04() { if (singleTon_04 == null) { synchronized (SingleTon_04.class) { singleTon_04 = new SingleTon_04(); } } return singleTon_04; } }
-
静态内部类实现
-
通过classloader机制确保初始化时只有一个线程
/*静态内部类*/ public class SingleTon_05 { private static class InstanceHolder{ private static SingleTon_05 singleTon_05 = new SingleTon_05(); } private SingleTon_05() { } public SingleTon_05 getSingleTon_05() { return InstanceHolder.singleTon_05; } }
enum实现
public enum SingleTon_06 {
INSTANCE;
public void print() {
System.out.println("singleTon_06");
}
}