1、饿汉式
package com.zjl.single;
/**
* Created by zjl
* 2020/10/29
**/
//饿汉式单利
public class Hungry {
//可能浪费空间
private byte[] data1 = new byte[1024*1024];
private byte[] data2 = new byte[1024*1024];
private byte[] data3 = new byte[1024*1024];
private Hungry(){
System.out.println(Thread.currentThread().getName() + "-----------------ok");
}
private final static Hungry HUNGRY = new Hungry();
public static Hungry getInstance(){
return HUNGRY;
}
//多线程并发测试
public static void main(String[] args) {
for (int i = 0; i < 10; i++) {
new Thread(()->{
Hungry.getInstance();
}).start();
}
}
}
测试结果
多线程并发测试也没有问题,只执行了一次构造方法,只有创建了一个对象。
2、懒汉式
package com.zjl.single;
/**
* Created by zjl
* 2020/10/29
**/
public class LazyMan {
private LazyMan(){
System.out.println(Thread.currentThread().getName() + "ok");
}
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 < 10; i++) {
new Thread(()->{
LazyMan.getInstance();
}).start();
}
}
}
测试结果:
我们想要得到的结果:只输出一次 ”ok“ ,因为当第一次生成实例后,后面只需要拿去实例,不需要再次进行创建实例对象,也就是不需要再进行初始化方法,也就不会再输出”ok“。
实际得到的结果:说明此代码有问题,需要完善
完善后的代码
package com.zjl.single;
/**
* Created by zjl
* 2020/10/29
**/
public class LazyMan {
private LazyMan(){
System.out.println(Thread.currentThread().getName() + "ok");
}
private volatile static LazyMan lazyMan;
//双重校验锁模式的 懒汉式单利 DCL懒汉式
public static LazyMan getInstance(){
if(lazyMan==null){
synchronized (LazyMan.class) {
if (lazyMan == null) {
lazyMan = new LazyMan();
}
}
}
return lazyMan;
}
//多线程并发测试
public static void main(String[] args) {
for (int i = 0; i < 10; i++) {
new Thread(()->{
LazyMan.getInstance();
}).start();
}
}
}
运行结果:
但是,此时还可能会发生问题,因为new LazyMan(); 这个操作不是原子性操作
双重校验锁,加原子性操作的代码如下
package com.zjl.single;
/**
* Created by zjl
* 2020/10/29
**/
public class LazyMan {
private LazyMan(){
System.out.println(Thread.currentThread().getName() + "ok");
}
//volatile 原子性操作
private volatile static LazyMan lazyMan;
//双重校验锁模式的 懒汉式单利 DCL懒汉式
public static LazyMan getInstance(){
if(lazyMan==null){
synchronized (LazyMan.class) {
if (lazyMan == null) {
lazyMan = new LazyMan(); //不是一个原子性操作
/**
* 1、分配内存空间
* 2、执行构造方法,初始化对象
* 3、把这个对象指向这个空间
*
* 我们期望执行顺序 123
*
* 实际执行顺序可能是 132 A
* B //此时lazyMan没有完成构造
*/
}
}
}
return lazyMan;
}
//多线程并发测试
public static void main(String[] args) {
for (int i = 0; i < 10; i++) {
new Thread(()->{
LazyMan.getInstance();
}).start();
}
}
}