设计模式-懒汉式单例的2种方式
没加锁的懒汉式单例,单线程状态下没问题,但是多线程环境下,可能创建出来的就不是单例
package singleton;
public class LazySingleton {
private LazySingleton() {
System.out.println(Thread.currentThread().getName()+
"线程不安全的单例模式,调用了构造器,被创建了");
}
private static LazySingleton INSTANCE = null;
public static LazySingleton getInstance() {
if (INSTANCE == null) {
INSTANCE = new LazySingleton();
}
return INSTANCE;
}
}
双检锁的方式
package singleton;
public class DclLazySingleton {
private DclLazySingleton() {
System.out.println(Thread.currentThread().getName()
+"双检锁的懒汉,调用了构造器,被创建了");
}
private static volatile DclLazySingleton INSTANCE = null;
public static DclLazySingleton getInstance() {
if (INSTANCE == null) {
synchronized (DclLazySingleton.class) {
if (INSTANCE == null) {
INSTANCE = new DclLazySingleton();
}
}
}
return INSTANCE;
}
}
单线程环境两种懒汉单例测试
package singleton;
public class TestLazySingleton {
public static void main(String[] args) {
LazySingleton instance1 = LazySingleton.getInstance();
LazySingleton instance2 = LazySingleton.getInstance();
System.out.println("位置1:"+(instance1 == instance2));
//DCL 双重检测锁的懒汉单例
DclLazySingleton dclLazySingleton1 = DclLazySingleton.getInstance();
DclLazySingleton dclLazySingleton2 = DclLazySingleton.getInstance();
System.out.println("位置2:"+(dclLazySingleton1 == dclLazySingleton2));
}
}
输出:
main线程不安全的单例模式,调用了构造器,被创建了
位置1:true
main双检锁的懒汉,调用了构造器,被创建了
位置2:true
多线程环境两种懒汉单例测试
package singleton;
public class TestMulThreadLazySingleton {
public static void main(String[] args) {
for (int i = 0; i < 50; i++) {
new Thread(new Runnable() {
@Override
public void run() {
LazySingleton.getInstance();
}
}).start();
}
System.out.println("--------------------------------");
for (int i = 0; i < 50; i++) {
new Thread(new Runnable() {
@Override
public void run() {
DclLazySingleton.getInstance();
}
}).start();
}
}
}
输出:
Thread-0线程不安全的单例模式,调用了构造器,被创建了
Thread-11线程不安全的单例模式,调用了构造器,被创建了
Thread-9线程不安全的单例模式,调用了构造器,被创建了
Thread-1线程不安全的单例模式,调用了构造器,被创建了
Thread-5线程不安全的单例模式,调用了构造器,被创建了
Thread-8线程不安全的单例模式,调用了构造器,被创建了
Thread-6线程不安全的单例模式,调用了构造器,被创建了
Thread-3线程不安全的单例模式,调用了构造器,被创建了
Thread-2线程不安全的单例模式,调用了构造器,被创建了
Thread-7线程不安全的单例模式,调用了构造器,被创建了
Thread-10线程不安全的单例模式,调用了构造器,被创建了
Thread-4线程不安全的单例模式,调用了构造器,被创建了
--------------------------------
Thread-50双检锁的懒汉,调用了构造器,被创建了
总结:
通过以上的结果可以看到,在单线程环境下,两种方式的构造方法都只调用了一次。
但是在多线程环境下,第一个懒汉单例,没有加锁,他的构造方法被多个线程调用,导致创建了多个对象。