目录
- 1.0立即加载/“饿汉式”
- 2.0延迟加载/“懒汉式”
- 3.0使用静态内置类实现单例模式
- 4.0序列化与反序列化的单例模式实现
- 5.0使用static代码块实现单例模式
- 6.0使用enum枚举数据类型实现单例模式
- 7.0完善使用enum枚举实现单例模式
1.0立即加载/“饿汉式”
立即加载:实用类的时候已经将对象创建完毕,常见的实现方法就是直接new实例化。
注:是在调用方法前,就已经实例化了(通常是在类一加载的时候就已经实例化了)。
public class Singleton {
//立即加载方法==饿汉式
private static Singleton singleton = new Singleton(); private Singleton() {
} public static Singleton getInstance() {
//此代码版本为立即加载
//此代码版本缺点:是不能有其他实例变量
//因为getInstance()方法没有同步
//所以可能出现非线程安全问题
return singleton;
}
}
2.0延迟加载/“懒汉式”
延迟加载:在调用get()方法时实例才被创建,常见的实现办法就是在get()中进行实例化。
注:在调用获取实例的方法时,实例才被创建。
public class Singleton {
private static Singleton singleton; private Singleton(){} public static Singleton getInstance() {
//延迟加载,若多个线程在此if失去执行权,最终会产生很多实例对象
if (singleton == null) {
singleton = new Singleton();
}
return singleton;
}
}
可以使用synchronized方法或者synchronized同步代码块解决多线程中的同步问题,但是效率较低。
书中提供了双检查锁机制:
可以使用DCL双检查锁机制实现单例:
public class Singleton {
private volatile static Singleton singleton; private Singleton(){}
//使用双检查锁机制来解决问题,既保证了不需要使用同步代码块的异步执行性,又保证了单例效果。 public static Singleton getInstance() {
if (singleton == null) {
synchronized (Singleton.class) {
if (singleton == null) {
singleton = new Singleton();
}
}
}
return singleton;
}
}
注:关于双检索的争议还是有很多的,但是目前可以认为其实安全的。
双检查锁的安全性问题总结(未完成)
3.0使用静态内置类实现单例模式
public class Singleton {
//内部类形式
private static class MyHanlder {
private static Singleton singleton = new Singleton();
} private Singleton() {} public static Singleton getInstance() {
return MyHanlder.singleton;
}
}
4.0序列化与反序列化的单例模式实现
虽然静态内置类可以达到线程安全,但如果遇到序列化对象,使用默认的方式运行得到的还是多例。
public class Singleton implements Serializable{
private static final long seroalVersionUID = 888L; //内部类形式
private static class MyHanlder {
private static Singleton singleton = new Singleton();
} private Singleton() {} public static Singleton getInstance() {
return MyHanlder.singleton;
} protected Object readResolve() throws ObjectStreamException {
return MyHanlder.singleton;
}
}
书写readResolve()方法就可以避免在序列化与反序列化的过程中单例失效。
注:目前为什么这样还不理解。
5.0使用static代码块实现单例模式
静态代码块中的代码在使用类的时候就已经执行了,所以可以应用静态代码块的这个特性来实现单例设计模式。
public class Singleton implements Serializable{
private static Singleton singleton = null; private Singleton() {} static {
singleton = new Singleton();
} public static Singleton getInstance() {
return singleton;
}
}
6.0使用enum枚举数据类型实现单例模式
枚举与静态代码块类似,在使用枚举时,构造方法会被自动调用,也可以使用其这个特性实现单例设计模式。