单例模式

avatar

参考1

前言

单例模式(Singleton Pattern)是 Java 中最简单的设计模式之一。这种类型的设计模式属于创建型模式,它提供了一种创建对象的最佳方式。

这种模式涉及到一个单一的类,该类负责创建自己的对象,同时确保只有单个对象被创建。这个类提供了一种访问其唯一的对象的方式,可以直接访问,不需要实例化该类的对象。

——菜鸟教程

才毕业在面试的时候百分之九十会遇到的面试题,手写至少两种方式;而我就会写懒汉式和恶汉式,其他的一概不知到怎么写,如今刚好学到单例模式,就做了这篇笔记;

正文

单例模式的写法有很多方式,下面主要写五种书写方式,不能保证完全正确;

懒汉式

首先是常写的一种:

1
2
3
4
5
6
7
8
9
10
11
12

// 懒汉式
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还是安全的,测试及结果如下:

测试:

1
2
3
4
5
6
7
8
9
10
11

public class Singleton{
    @Rule
    public ContiPerfRule i = new ContiPerfRule();
    @Test
    @PerfTest(threads = 40000)
    public void test(){
        SingletonA.getInstance();
    }
}

结果:

1
2
3
4
5
6
7
8

com.example.demo.dao.Singleton.test
aa
samples: 1
max:     2
average: 2.0
median:  2

也许是我测试出了问题,具体原因得去深究一下;

恶汉式

直接上代码:

1
2
3
4
5
6
7
8
9
10
11
12
13

//恶汉式
class SingletonB{
     //类加载时就初始化
    private static final SingletonB singletonB=new SingletonB();
    private SingletonB(){
        System.out.println("bb");
    }
    public static SingletonB getInstance(){
        return singletonB;
    }
}

因为在类加载的时候就进行了初始化,而且实例被 staticfinal声明,所以创建实例是线程安全的;

双重检验锁

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17

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》上所推荐的

1
2
3
4
5
6
7
8
9
10
11
12
13

//静态内部类
class SingletonD{
    private static class SingletonHolder{
        private static final SingletonD INSTANCE=new SingletonD();
    }
    private SingletonD(){
    }
    public static final SingletonD getInstance(){
        return SingletonHolder.INSTANCE;
    }
}

枚举

这是最简单的写法,

1
2
3
4
5
6

//枚举写法
 enum SingletonE {
    INSTANCE;
}

最后

如果需要看每种方法的详细解释,可以点击参考链接

坚持原创技术分享,您的支持将鼓励我继续创作!