单例模式2
- 单例模式
引子:
Java类加载器加载内容的顺序:
1、从上往下(Java的变量需要先声明才能使用)
2、静态后动态(对象实例化)(静态块和static关键字修饰在实例化以前分配内存空间)
3、先属性后方法(成员变量不能定义在方法中,只能定义在class下)
- 保证从系统启动到系统终止,全过程只会产生一个实例。
- 当我们在应用中遇到功能性冲突的时候,需要使用单例模式。
- 饿汉就是类一旦加载,就把单例初始化完成,保证getInstance的时候,单例是已经存在的了,
- 懒汉比较懒,只有当调用getInstance的时候,才回去初始化这个单例。
- 线程安全:
饿汉式天生就是线程安全的,可以直接用于多线程而不会出现问题,
懒汉式本身是非线程安全的,在实现线程安全的写法上,资源加载和性能方面也有些区别。 - 资源加载和性能:
饿汉式在类创建的同时就实例化一个静态对象出来,不管之后会不会使用这个单例,都会占据一定的内存,但是相应的,在第一次调用时速度也会更快,因为其资源已经初始化完成,
而懒汉式顾名思义,会延迟加载,在第一次使用该单例的时候才会实例化对象出来,第一次调用时要做初始化,如果要做的工作比较多,性能上会有些延迟,之后就和饿汉式一样了。
- 分布式环境下的单例
- 如果单例由不同的类装载器装入,那便有可能存在多个单例类的实例。假定不是远端存取,例如一些servlet容器对每个servlet使用完全不同的类装载器,这样的话如果有两个servlet访问一个单例类,它们就都会有各自的实例。
private static Class getClass(String classname) throws ClassNotFoundException {
ClassLoader classLoader = Thread.currentThread().getContextClassLoader();
if(classLoader == null){
classLoader = Singleton.class.getClassLoader();
}
return (classLoader.loadClass(classname));
}
- 如果Singleton实现了java.io.Serializable接口,那么这个类的实例就可能被序列化和复原。不管怎样,如果你序列化一个单例类的对象,接下来复原多个那个对象,那你就会有多个单例类的实例。
public class Singleton implements java.io.Serializable {
public static Singleton INSTANCE = new Singleton();
protected Singleton() { }
private Object readResolve() {
return INSTANCE;
}
}