SpringMVC框架中就有单例模式的引入 。它具有很高的实用性。
/**
* 单例模式:
* 几乎在每个用程序中,都需要有一个全局访问和维护某种数据类型的区域。
* 比如java语言基础一书中的订餐系统,
* 需要一个全局的初始化订单来保存其他类中接收的具体的订单数量。
* 大多数人可能会采用将初始化订单作为static全局静态变量进行访问。(我也这样做了)
* 但是,这种情况只解决了全局可访问的问题,
* 而没有采取任何措施来确保在任何给定的时间只运行一个实例。
* 这种情况下应该由类本身来负责只是用一个实例,而不是由类用户来负责。
* 也就是说,应该不要一直让订单类来控制类实例的数量。必须让初始化订单类来可控制实例的数量
*
* 特点:
* 1.单例类只能有一个实例
* 2.单例类必须自己创建一个自己的唯一实例
* 3.单例类必须给所有其他对象提供这一个唯一实例
*/
/*
* 初级:
* 懒汉式单例
* 在第一次调用时候就实例化自己
*/
public class LazySingleton {
/**
* private LazySingleton() {
* }
* private static LazySingleton single = null;
* public static LazySingleton getInstance(){
* if(single==null){
* single=new LazySingleton();
* }
* return single;
* }
*
* 私有构造方法,避免了类在外部就会被实例化。
* 在同一个虚拟机范围内,Singleton的唯一实例只能通过getInstance()获得
* 但是,懒汉式的单例模式实现没有考虑线程安全问题,在并发环境下可以出现多个实例。
* 要实现线程安全,只有对getInstance方法改造,来保证懒汉式单例的线程安全。
* 最好的方法是采用静态内部类来解决
*/
public static class LazyHolder{
private static final LazySingleton INSTANCE=new LazySingleton();
}
private LazySingleton(){
}
public static final LazySingleton getInstance(){
return LazyHolder.INSTANCE;
}
}
public class HungrySingleton {
/**
* 饿汉式单例
* 正在类初始化时,已经自行实例化
* 饿汉式单例在类创建的同时就已经创建好了一个静态的对象提供给系统使用。
* 以后不再改变。所以天生线程安全。
*/
private HungrySingleton(){
}
private static final HungrySingleton single=new HungrySingleton();
/**
* 静态工厂方法
*/
public static HungrySingleton getInstance(){
return single;
}
}
懒汉式和饿汉式的区别:
- 线程安全
- 饿汉式天生线程安全,由于第一次就创建了唯一的静态对象,可以只直接用于多线程而不会出现问题。
- 懒汉式本身是非线程安全的,如果多个线程并行进入时,会创建多个静态实例,但是静态内部类会解决线程问题而且没有性能损耗,推荐使用。
- 资源加载和性能
- 饿汉式性能更快,但是占用内存。在类创建的同时就实例化出一个静态对象,不管之后会不会使用这个单例,都会占用一定内存;但是相应的之后调用会时速更快。因为资源初始化已经完成。
- 懒汉式延迟加载,内存占用少,但是性能较低。但是加入了静态内部类的懒汉式单例模式,利用ClassLoader的机制来保证线程问题,并且没有性能损耗。