单例模式:一个类只有一个实例,自行实例化向整个系统提供这个实例。
特点:
1.构造函数私有化,保证只提供唯一实例。
2.私有化创建自身的唯一实例。
3.公共静态类返回这一实例。
分类:懒汉模式,饿汉模式
懒汉模式:
public class Singleton {
private Singleton() {}
private static Singleton single=null;
public synchronized static Singleton getInstance() {
if (single == null) {
single = new Singleton();
}
return single;
}
}
延迟加载,当用到这个单利时,才会初始化这个单利,线程不安全的,例如:假设线程A、B在执行中,A先做了判断,发现instance为空,正当它准备执行下一句的时候,JVM将处理器资源分配给了线程B,它又做了一次判断,但B也发现instance为空,因为A还没有执行下一句,内存还未分配,于是B执行了初始化new操作,当JVM把A唤醒的时候,它又进行了一次初始化,这样你的instance就做了两次初始化,就出现了多个instance实例。因此需要使用synchronized实现线程安全。但是使用synchronized实现线程安全同时也带来性能消耗,因为在初次使用时保证了线程安全,但之后的调用不需要再使用synchronized,因此也不理想。
饿汉模式:
public class Singleton1 {
private Singleton1() {}
private static final Singleton1 single = new Singleton1();
public static Singleton1 getInstance() {
return single;
}
}
饿汉模式会随着类的加载而加载,是线程安全的。static变量会在类加载时就被创建,而不是在实例化的时候,保证了单例对象的唯一性。但是没有延迟加载的效果。因此也不理想
优化后的单利模式:
public class Singleton {
private static class LazyHolder {
private static final Singleton INSTANCE = new Singleton();
}
private Singleton (){}
public static final Singleton getInstance() {
return LazyHolder.INSTANCE;
}
}
通过静态内部类的方式实现了 延迟加载也保证了线程安全。
单利模式在java中的应用:
1,spring中bean的作用域 scope="singleton" 默认为单利模式 修改为prototype为多利
2,日期类型:Calendar calender=Calendar.getInstance();
3,配置文件连接 如redis ,数据库连接