使用该类的时候才初始化该类
//代码实现public class LazyMan {
private LazyMan(){}
private static LazyMan lazyMan;
public static LazyMan getInstance(){
if (lazyMan == null){
lazyMan = new LazyMan();
}
return lazyMan;
}
}
在多线程下使用饿汉式单例,8个线程可能有多个线程能使用该类的构造方法,说明懒汉式单例是线程不安全的
public class LazyMan {
private LazyMan(){
System.out.println("懒汉式单例 " + Thread.currentThread().getName());
}
private static LazyMan lazyMan;
public static LazyMan getInstance(){
if (lazyMan == null){
lazyMan = new LazyMan();
}
return lazyMan;
}
public static void main(String[] args) {
for (int i = 0; i <9 ; i++) {
new Thread(()->{
LazyMan.getInstance();
}).start();
}
}
}
/*
输出结果:
懒汉式单例 Thread-0
懒汉式单例 Thread-2
懒汉式单例 Thread-1
*/
优点:
节省内存空间
缺点:
线程不安全
3、DCL懒汉式(双重检查懒汉式)
解决懒汉式线程不安全的问题
//代码实现public class DCLLazyMan {
private DCLLazyMan(){}
/*
volatile:
在原子性上来说是不安全的:
new DCLLazyMan(),创建对象的实例会分解成以下3个指令
•1、分配内存空间
•2、执行构造方法,初始化对象
•3、对象指向内存空间
我们期望按1 2 3 的顺序依次完成,但是在内存中会出现指令重排的过程:
假设A类new DCLLazyMan(),是先分配内存空间、占用此空间、初始化对象,也就是132的顺序执行,
同时另一个线程中的B类也在new DCLLazyMan(),此时A还没有完成DCLLazyMan的构造,就会出现不 安全的问题。
必须加上volatile关键字!
*/
private volatile static DCLLazyMan lazyMan;
public static DCLLazyMan getInstance(){
//第一重检查
if (lazyMan == null){
//加锁
synchronized (DCLLazyMan.class){
//第二重检查
if (lazyMan == null){
lazyMan = new DCLLazyMan();
}
}
}
return lazyMan;
}
}