单例模式
前言
单例模式(Singleton Pattern)是 Java 中最简单的设计模式之一。这种类型的设计模式属于创建型模式,它提供了一种创建对象的最佳方式。
这种模式涉及到一个单一的类,该类负责创建自己的对象,同时确保只有单个对象被创建。这个类提供了一种访问其唯一的对象的方式,可以直接访问,不需要实例化该类的对象。
------菜鸟教程
才毕业在面试的时候百分之九十会遇到的面试题,手写至少两种方式;而我就会写懒汉式和恶汉式,其他的一概不知到怎么写,如今刚好学到单例模式,就做了这篇笔记;
正文
单例模式的写法有很多方式,下面主要写五种书写方式,不能保证完全正确;
懒汉式
首先是常写的一种:
// 懒汉式
class SingletonA {
private static SingletonA singletona;
private SingletonA(){
System.out.println("aa");
}
public static SingletonA getInstance(){
return singletona == null ?new SingletonA():singletona;
}
}
注意:这样写是线程不安全的,如果要使其线程安全,只需要给getInstance
方法加上synchronized
就行了;
出现的疑问:我使用 ContiPerf 简单测试了一下,没加synchronized
还是安全的,测试及结果如下:
测试:
public class Singleton{
@Rule
public ContiPerfRule i = new ContiPerfRule();
@Test
@PerfTest(threads = 40000)
public void test(){
SingletonA.getInstance();
}
}
结果:
com.example.demo.dao.Singleton.test
aa
samples: 1
max: 2
average: 2.0
median: 2
也许是我测试出了问题,具体原因得去深究一下;
恶汉式
直接上代码:
//恶汉式
class SingletonB{
//类加载时就初始化
private static final SingletonB singletonB=new SingletonB();
private SingletonB(){
System.out.println("bb");
}
public static SingletonB getInstance(){
return singletonB;
}
}
因为在类加载的时候就进行了初始化,而且实例被 static
和final
声明,所以创建实例是线程安全的;
双重检验锁
class SingletonC{
private static SingletonC singletonC;
private SingletonC(){
System.out.println("cc");
}
public static SingletonC getInstance(){
if(singletonC==null){
synchronized (SingletonC.class){
if (singletonC==null)
singletonC= new SingletonC();
}
}
return singletonC;
}
}
静态内部类
《Effective Java》上所推荐的
//静态内部类
class SingletonD{
private static class SingletonHolder{
private static final SingletonD INSTANCE=new SingletonD();
}
private SingletonD(){
}
public static final SingletonD getInstance(){
return SingletonHolder.INSTANCE;
}
}
枚举
这是最简单的写法,
//枚举写法
enum SingletonE {
INSTANCE;
}
最后
如果需要看每种方法的详细解释,可以点击参考链接