单例(Singleton)模式的定义:指一个类只有一个实例,且该类能自行创建这个实例的一种模式。例如,Windows 中只能打开一个任务管理器,这样可以避免因打开多个任务管理器窗口而造成内存资源的浪费,或出现各个窗口显示内容的不一致等错误。
在计算机系统中,还有 Windows 的回收站、操作系统中的文件系统、多线程中的线程池、显卡的驱动程序对象、打印机的后台处理服务、应用程序的日志对象、数据库的连接池、网站的计数器、Web 应用的配置对象、应用程序中的对话框、系统中的缓存等常常被设计成单例。
单例模式有 3 个特点:
单例类只有一个实例对象;
该单例对象必须由单例类自行创建;
单例类对外提供一个访问该单例的全局访问点;
单例模式的结构与实现
单例模式是设计模式中最简单的模式之一。通常,普通类的构造函数是公有的,外部类可以通过“new 构造函数()”来生成多个实例。但是,如果将类的构造函数设为私有的,外部类就无法调用该构造函数,也就无法生成多个实例。这时该类自身必须定义一个静态私有实例,并向外提供一个静态的公有函数用于创建或获取该静态私有实例。
实例:单例模式之懒汉模式模式
在类的对象第一次使用时才创建该实例
public classSingleTonLH {/** 构成单例的条件
* 1.保证不能让其他人使用构造器创建对象
* 2.提供一个静态方法,用于返回该对象*/
private static SingleTonLH instance = null;privateSingleTonLH(){}
public staticSingleTonLH getInstance(){if(instance == null){synchronized(SingleTonLH.class){if(instance == null){
instance= newSingleTonLH();
}
}
}returninstance;
}
}
实例:单例模式之饿汉模式模式
在类被加载的时候,就创建好了实例。
public classSingleTonEL {/** 构成单例的条件
* 1.保证不能让其他人使用构造器创建对象
* 2.提供一个静态方法,用于返回该对象*/
private static SingleTonEL instance = newSingleTonEL();privateSingleTonEL(){}public staticSingleTonEL getInstance(){returninstance;
}
}
单例模式的典型应用
这里不得不提到Servlet也是单例的。
为什么Servlet是单例的?
浏览器多次对Servlet的请求,一般情况下,服务器只创建一个Servlet对象,也就是说,Servlet对象一旦创建了,就会驻留在内存中,为后续的请求做服务,直到服务器关闭。
每次访问请求对象和响应对象都是新的
对于每次访问请求,Servlet引擎都会创建一个新的HttpServletRequest请求对象和一个新的HttpServletResponse响应对象,然后将这两个对象作为参数传递给它调用的Servlet的service()方法,service方法再根据请求方式分别调用doXXX方法。
线程安全问题
当多个用户访问Servlet的时候,服务器会为每个用户创建一个线程。当多个用户并发访问Servlet共享资源的时候就会出现线程安全问题。
原则:
如果一个变量需要多个用户共享,则应当在访问该变量的时候,加同步机制synchronized (对象){}
如果一个变量不需要共享,则直接在 doGet() 或者 doPost()定义.这样不会存在线程安全问题
load-on-startup配置项
如果在元素中配置了一个元素,那么WEB应用程序在启动时,就会装载并创建Servlet的实例对象、以及调用Servlet实例对象的init()方法。