一、单例模式特点:
- 该类只能有一个实例;
- 所有的使用方必须通过同一访问点来访问这个实例。
二、创建单例的方法—懒汉法:
- 把类的构造方法设为private,来防止外界调用它;
- 在类中创建一个对象实例;
- 实现一个供外界访问的getInstance()函数。
public class Singleton {
//1.构造方法私有化,外部不能new
private Singleton(){
}
//2.本类内部创建对象实例
private static Singleton instance = null;
//3.提供一个公有的静态方法,返回实例对象
public static Singleton getInstance() {
if (instance == null) {
instance = new Singleton();
}
return instance;
}
}
上述实现单例模式的方法是线程不安全的,在多线程的环境下,如果不对返回的实例加锁,就可能出现多个线程创建出多个实例的情况。可以使用synchronized 关键字用来实现线程安全。synchronized 关键字可以保证在同一时刻,只有一个线程可以执行某个方法或某个代码块,从而实现线程安全,但是开销大,效率低。
public class Singleton {
//2.本类内部创建对象实例
private static Singleton instance = null;
//1.构造方法私有化,外部不能new
private Singleton(){
}
//3.提供一个公有的静态方法,返回实例对象
public static Singleton getInstance() {
if (instance == null) {
//synchronized 关键字用来实现线程安全
synchronized(Singleton.class){
if (instance == null) {
instance = new Singleton();
}
}
}
return instance;
}
}
三、创建单例的方法—饿汉法:
public class ESingleton{
//初始化时就建立对象
private static ESingleton instance = new ESingleton();
private ESingleton(){
}
public static ESingleton getInstance(){
return instance;
}
}
四、懒汉法与饿汉法区别
所谓“懒汉式”与“饿汉式”的区别,在于建立单例对象的时间的不同。“懒汉式”是在你真正用到的时候(程序第一次访问单件模式实例时)才去建这个单例对象, “饿汉式”是在不管你用的用不上,在程序启动或单件模式类被加载的时候,一开始就建立这个单例对象。
懒汉式:线程不安全。
饿汉式:线程安全,调用效率高。但是不能延时加载。
如何选择: 如果单件模式实例在系统中经常会被用到,饿汉式是一个不错的选择。
反之如果单件模式在系统中会很少用到或者几乎不会用到,那么懒汉式是一个不错的选择。
五、单例模式常见应用场景
- 网站计数器。
- 项目中用于读取配置文件的类。
- 数据库连接池。因为数据库连接池是一种数据库资源。
- Spring中,每个Bean默认都是单例的,这样便于Spring容器进行管理。
- Servlet中Application
- Windows中任务管理器,回收站。