1 饿汉式
/**
* @author :wyaoyao
* @date : 2020-04-06 14:32
* 单例模式:饿汉式
* 线程安全
* 但是在不使用的时候占用内存,因为通过static是类主动加载,不能能够懒加载
*/
public class SingletonSimple1 {
private static final SingletonSimple1 instance = new SingletonSimple1();
// 构造私有化。不允许外部调用
private SingletonSimple1() {
}
public static SingletonSimple1 getInstance() {
return instance;
}
}
- 线程安全
- 但是在不使用的时候占用内存,通过static是类主动加载,不能能够懒加载
测试
// 测试
@Test
public void test() {
SingletonSimple1 instance1 = SingletonSimple1.getInstance();
SingletonSimple1 instance2 = SingletonSimple1.getInstance();
Assert.assertTrue(instance1 == instance2);
}
懒汉式
/**
* @author :wyaoyao
* @date : 2020-04-06 14:41
* 饿汉式:懒加载
*/
public class SingletonSimple2 {
private static SingletonSimple2 instance;
private SingletonSimple2(){
}
// 存在线程安全问题
public static SingletonSimple2 getInstance(){
if(null == instance){
instance = new SingletonSimple2();
}
return instance;
}
}
- 这个懒加载,在使用的时候才会创建对象,但是线程不安全
测试
// 测试,构建100线程去创建对象,测试是否线程安全
@Test
public void test2() {
for (int i = 0; i<100; i++){
new Thread(()->{
SingletonSimple2 instance = SingletonSimple2.getInstance();
System.out.println(instance);
},"T"+i).start();
}
/**
* 不安全,并不是单例的,SingletonSimple2@608f35ee,SingletonSimple2@5617e729
* study.wyy.concurrency.designpatterns.singleton.SingletonSimple2@608f35ee
* study.wyy.concurrency.designpatterns.singleton.SingletonSimple2@5617e729
* study.wyy.concurrency.designpatterns.singleton.SingletonSimple2@7df5ed4e
* study.wyy.concurrency.designpatterns.singleton.SingletonSimple2@7df5ed4e
* study.wyy.concurrency.designpatterns.singleton.SingletonSimple2@7df5ed4e
*/
}
解决懒汉式的线程不安全
方案一
// 加锁
public synchronized static SingletonSimple2 getInstance(){
if(null == instance){
instance = new SingletonSimple2();
}
return instance;
}
问题
- 除了第一次是创建,以后都是读的操作,每次都会加锁,效率不高
方案二
double check
public class SingletonSimple3 {
private static SingletonSimple3 instance;
private SingletonSimple3(){
}
public static SingletonSimple3 getInstance(){
if(null == instance){
synchronized (SingletonSimple3.class){
if(null == instance){
instance = new SingletonSimple3();
}
}
}
return SingletonSimple3.instance;
}
}
也存在问题:可能会引起npe
解决这个问题很简单,使用volatile关键字即可
public class SingletonSimple3 {
private static volatile SingletonSimple3 instance;
private SingletonSimple3(){
}
public static SingletonSimple3 getInstance(){
if(null == instance){
synchronized (SingletonSimple3.class){
if(null == instance){
instance = new SingletonSimple3();
}
}
}
return SingletonSimple3.instance;
}
}
ClassHolder
- 支持懒加载
- 线程安全
- 不会npe
public class SingletonSimple5 {
private SingletonSimple5(){
}
private static class InstanceHolder {
private final static SingletonSimple5 instance = new SingletonSimple5();
}
public static SingletonSimple5 getInstance(){
return InstanceHolder.instance;
}
}