什么是单例模式
单例模式(Single Pattern),被单例的对象只能有一个实例存在。单例模式的实现方式是,一个类只能返回对象的一个引用和一个获得该唯一实例的方法(此方法必须是静态方法)。
为什么要使用单例设计模式
通过单例模式,可以保证系统中只有一个实例,从而在某些特定的场合下达到节约或者控制系统资源
单例模式分类及其代码实现
1.饿汉模式
一开始就创建一个实例。虽然较为简单和常见。但有一个明显的缺点,就是不管有没有调用过获得实例的方法,都会创建一个实例。
public class Single {
private static final Single single = new Single();
private Single(){}
public static Single getSingle(){
return single;
}
}
2.懒汉模式
他改进了上述"饿汉模式"的不足之处,调用getSingle() 方法时首先判断实例是否为空,为空才创建实例,并且是调用方法时才创建
public class Single {
private static Single single;
private Single(){}
public static Single getSingle(){
if (single == null){
single = new Single();
}
return single;
}
}
3.线程安全的懒汉模式
懒汉模式也存在问题。那就是如果有多个线程并行调用getSingle() 方法的时候,还是会创建多个实例,那单例子模式就失效了。所以在此基础上设置线程同步(关键子synchonized)。synchronized的作用就是保证在同一时刻最多只有一个线程运行,这样就避免了多线程带来的问题 。
public class Single {
private static Single single;
private Single(){}
public static synchronized Single getSingle(){
if (single == null){
single = new Single();
}
return single;
}
}
4.双重检验锁
上述解决方法,也不是完美的。每次调用getSingle()时都要进行线程同步,考虑一下这种情况,single对象已经创建了,本来直接返回对象使用即可,但却又要进行线程同步。
于是在此基础之上,又有了双重检验锁的方法
public class Single {
private volatile static Single single;
private Single(){}
public static Single getSingle(){
if (single == null){
synchronized (Single.class){
if(single == null){
single = new Single();
}
}
}
return single;
}
}
- 注意
还需要给实例加一个 volatile 关键字,它的作用就是防止编译器自行优化代码,以保证代码的运行顺序是固定不变的。这涉及到JVM的代码优化机制。
5.静态内部类
上述方法不断改进,有点复杂,其实完全可以通过静态内部类来保证线程安全。
public class Single {
private static class SingleHoder{
private static final Single single = new Single();
}
private Single(){}
public static Single getSingle(){
return SingleHoder.single;
}
}
Single类是私有的,除getSingle()方法*之外没有其他方式可以访问到实例,而且只有调用改方法时才会去创建实例对象。
6.枚举
这种方法最为简单。我们可以通过Single.INSANCE来访问实例,并且创建枚举默认就是线程安全的,还可以防止反序列化带来的问题。
public enum Single {
INSTANCE;
public void whateverMethod(){};
}
关于作者
个人博客: http://yhch.xyz
网友评论