1、作用:让应用程序保证最多只能有一个实例
2、好处:
- 提升运行效率
- 实现数据共享,案例:application 对象
3、四种单例模式实现方式:
- 饿汉式(线程安全,调用效率高。 但是,不能延时加载)
- 懒汉式(线程安全,调用效率不高。 但是,可以延时加载)
- 静态内部类式(线程安全,调用效率高。 但是,可以延时加载)
- 枚举式(线程安全,调用效率高,不能延时加载。并且可以防止反射和反序列化漏洞!)
4、代码示例
- 1、饿汉式:
- 线程安全,调用效率高
- 缺点:类初始化时,立即加载这个对象,不能延时加载,可能在还不需要此实例的时候就已经把实例创建出来了
public class SingletonDemo1 {
private static SingletonDemo1 instance = new SingletonDemo1();
private SingletonDemo1(){}
public static SingletonDemo1 getInstance(){
return instance;
}
}
- 2、懒汉式:
- 线程安全,调用效率不高
- 类初始化时,不初始化这个对象,延时加载,真正用的时候再创建。
public class SingletonDemo2 {
private static SingletonDemo2 instance;
private SingletonDemo2(){}
public static synchronized SingletonDemo2 getInstance(){
if(instance==null){
instance = new SingletonDemo2();
}
return instance;
}
}
- 在并发获取实例的时候,可能会存在构建了多个实例的情况,可加双重锁
public class SingleTon {
private static SingleTon singleton;
private SingleTon(){}
public static SingleTon getInstance(){
if(singleton == null){
synchronized (SingleTon.class) {
if(singleton == null){
singleton = new SingleTon();
}
}
}
return singleton;
}}
- 3、静态内部类式:
- 线程安全,调用效率高。可以延时加载
- 可能存在反射和反序列化漏洞
public class SingletonDemo3 {
private static class SingletonClassInstance {
private static final SingletonDemo3 instance = new SingletonDemo3();
}
private SingletonDemo3(){}
public static SingletonDemo3 getInstance(){
return SingletonClassInstance.instance;
}
}
- 4、枚举式:
- 最佳的单例实现模式,写法简单
- 线程安全,调用效率高,不能延时加载。并且可以防止反射和反序列化漏洞!
public enum SingletonDemo4 {
//这个枚举元素,本身就是单例对象!
INSTANCE;
public void singletonOperation(){
//此处可添加自己需要的操作!
}
}
调用方法:
public class Main {
public static void main(String[] args) {
SingletonDemo4.INSTANCE.singletonOperation();
}
}
5、总结:如何选用?
- 单例对象 占用资源少,不需要延时加载:
- 枚举式 好于 饿汉式
- 单例对象 占用资源大,需要延时加载:
- 静态内部类式 好于 懒汉式