几种模式实现优缺点
1.饿汉式
package com.jiawei.pattern;
import java.util.*;
import java.util.concurrent.*;
/**
* @version 1.0
* @Description: 饿汉式 -- 类初始化即实例化对象
* @Author: hongjiawei
* @Date: Created in 2021/3/20
*/
public class ErHanSingleton {
/**
* static 类初始化即实例化,不需要等用到,只会实例化一次
*/
private static ErHanSingleton singleton = new ErHanSingleton();
/**
* 私有化构造
*/
private ErHanSingleton() {
// can not call
}
/**
* 对外提供的获取实例方法public
*
* @return 单例对象
*/
public static ErHanSingleton getInstance() {
return singleton;
}
/**
* main方法测试是否是线程安全
*
* @param args
*/
public static void main(String[] args) throws InterruptedException {
Set<ErHanSingleton> objectSet = new HashSet<>();
// 共享锁收集结果
CountDownLatch countDownLatch = new CountDownLatch(100);
for (int i = 0; i < 100; i++) {
new Thread(() -> {
ErHanSingleton instance = ErHanSingleton.getInstance();
objectSet.add(instance);
// 执行完一个线程就释放一个锁
countDownLatch.countDown();
}).start();
}
// 开关
countDownLatch.await();
System.out.println(objectSet.size() == 1);
// 结果为true,线程安全,原理为类加载机制,类加载原理可看https://editor.csdn.net/md/?articleId=114500006
}
}
2.懒汉式
package com.jiawei.pattern;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.concurrent.*;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.stream.Collectors;
/**
* @version 1.0
* @Description: 懒汉式 延迟加载,使用时才实例化
* @Author: hongjiawei
* @Date: Created in 2021/3/21
*/
public class LanHanSingleton {
/**
* static 初始化为null,不会开辟堆空间
*/
private static LanHanSingleton singleton;
/**
* 私有化构造
*/
private LanHanSingleton() {
// can not call
System.out.println("被new了........");
}
/**
* 对外提供的获取实例方法public
*
* @return 单例对象
*/
public static LanHanSingleton getInstance() {
if (singleton == null) {
singleton = new LanHanSingleton();
}
return singleton;
}
/**
* main方法测试是否是线程安全
*
* @param args
*/
public static void main(String[] args) throws InterruptedException, ExecutionException {
Set<LanHanSingleton> objectSet = new HashSet<>();
// 共享锁收集结果
CountDownLatch countDownLatch = new CountDownLatch(100);
for (int i = 0; i < 100; i++) {
new Thread(() -> {
LanHanSingleton instance = LanHanSingleton.getInstance();
objectSet.add(instance);
// 执行完一个线程就释放一个锁
countDownLatch.countDown();
}).start();
}
// 开关
countDownLatch.await();
System.out.println(objectSet.size() == 1);
}
}
getInstance加上同步锁synchronized呢 再运行下结果
可以保证线程安全,但是不推荐这种写法,线程的锁互斥严重
3.双重锁 + volatile
package com.jiawei.pattern;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.concurrent.*;
import java.util.stream.Collectors;
/**
* @version 1.0
* @Description: 双重锁机制 需要避免指令重排序
* @Author: hongjiawei
* @Date: Created in 2021/3/21
*/
public class DoubleCheckSingleton {
/**
* static 初始化为null,不会开辟堆空间
* volatile 保证可见性 有序性,避免指令重排
*/
private static volatile DoubleCheckSingleton singleton;
/**
* 私有化构造
*/
private DoubleCheckSingleton() {
// can not call
System.out.println("被new了........");
}
/**
* 对外提供的获取实例方法public
*
* @return 单例对象
*/
public static DoubleCheckSingleton getInstance() {
if (singleton == null) {
synchronized (DoubleCheckSingleton.class) {
if (singleton == null) {
singleton = new DoubleCheckSingleton();
}
}
}
return singleton;
}
/**
* main方法测试是否是线程安全
*
* @param args
*/
public static void main(String[] args) throws InterruptedException, ExecutionException {
List<Callable<InnerClassSingleton>> callables = new ArrayList<>();
for (int i = 0; i < 10000; i++) {
Callable<InnerClassSingleton> instanceCallable = () -> {
InnerClassSingleton instance = InnerClassSingleton.getInstance();
return instance;
};
callables.add(instanceCallable);
}
List<Future<InnerClassSingleton>> futureList = Executors.newCachedThreadPool().invokeAll(callables);
Set<InnerClassSingleton> InnerClassSingletons = new HashSet<>();
for (Future<InnerClassSingleton> InnerClassSingletonFuture : futureList) {
InnerClassSingletons.add(InnerClassSingletonFuture.get());
}
System.out.println(InnerClassSingletons.size() == 1);
}
}
4.静态内部类
package com.jiawei.pattern;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
/**
* @version 1.0
* @Description: 静态内部类 依赖类加载器完成实例化,线程安全,常用
* @Author: hongjiawei
* @Date: Created in 2021/3/21
*/
public class InnerClassSingleton {
/**
* 私有化构造
*/
private InnerClassSingleton() {
// can not call
System.out.println("被new了........");
}
/**
* 对外提供的获取实例方法public
*
* @return 单例对象
*/
public static InnerClassSingleton getInstance() {
return Holder.innerClassSingleton;
}
/**
* 静态内部类
*/
static class Holder {
private static InnerClassSingleton innerClassSingleton = new InnerClassSingleton();
}
/**
* main方法测试是否是线程安全
*
* @param args
*/
public static void main(String[] args) throws InterruptedException, ExecutionException {
List<Callable<InnerClassSingleton>> callables = new ArrayList<>();
for (int i = 0; i < 10000; i++) {
Callable<InnerClassSingleton> instanceCallable = () -> {
InnerClassSingleton instance = InnerClassSingleton.getInstance();
return instance;
};
callables.add(instanceCallable);
}
List<Future<InnerClassSingleton>> futureList = Executors.newCachedThreadPool().invokeAll(callables);
Set<InnerClassSingleton> InnerClassSingletons = new HashSet<>();
for (Future<InnerClassSingleton> InnerClassSingletonFuture : futureList) {
InnerClassSingletons.add(InnerClassSingletonFuture.get());
}
System.out.println(InnerClassSingletons.size() == 1);
}
}