单例模式是设计模式中的其中一种创建型的模式。其特点是保证一个类只有一个实例,并且提供一个访问该实例的全局访问入口。线程安全,且降低系统性能消耗。

单例模式又分为饿汉、懒汉式、双重检测锁式、静态内部类式、枚举式

其中,最常用的有饿汉式和懒汉式。

饿汉式

1
2
3
4
5
6
7
8
9
10
11
12
13
public class Main{

/**创建一个私有的Main类实例对象**/
private static Main instace = new Main();

/**将Main的构造器私有*/
private Main(){}

/**只将唯一的公开方法作为返回,供其他类调用**/
public static Main getInstance(){
return instance;
}
}

特点:线程安全,调用效率高。
缺点:不能够延时加载

懒汉式

1
2
3
4
5
6
7
8
9
10
public class Main{
private static Main s;
private Main(){}
public static synchronized Main get Instance(){
if(s==null){
s = new Main;
}
return s;
}
}

特点:线程安全,可以延时加载。
缺点:调用效率不高。(遇到需要频繁调用时不建议使用此方法)

双重检测锁式

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
public class Main {
private static Main instance = null;
public static Main getInstance(){
if(instance == null){
Main m;
synchronized(Main.class){
m = instance;
if(m == null){
m = new Main();
}
}
instance = m;
}
return instance;
}
private Main(){}
}

特点:与懒汉式相似,但不必每次获取对象时都进行同步,只有第一次才同步,提高调用效率。
缺点:可能因为JVM底层内部模型问题,偶尔会出问题,不建议经常使用

静态内部类式

1
2
3
4
5
6
7
8
9
public class Main {
private static class Main02{
private static final Main instance = new Main();
}
public static Main getInstance(){
return Main02.instance;
}
private Main(){}
}

特点:
1.外部类没有static属性,不会像饿汉式那样立即加载对象。
2.只在真正调用getInstance(),才会加载静态内部类。加载类时是线程安全的。
3.保证内存中只有这样一个实例存在,而且只能赋值一次。

枚举式

1
2
3
4
5
6
7
8
9
10
11
public enum Main{
INSTANCE;
void Test(){
System.out.println("枚举单例");
}
}
class TestRun{
public static void main(String[]args){
Main.INSTANCE.Test();
}
}

特点:实现简单
缺点:无延迟加载

有关上述五种单例模式的效率测试

模式 速度
饿汉式 22 ms
懒汉式 636 ms
双重检测锁式 65 ms
静态内部类式 28 ms
枚举式 32ms