单例模式介绍
单例(Singleton)模式是在Java中最重要、最简单、最常用的设计模式之一
比如在现实生活中,男生只能有一个老婆,女生也只能有一个老公,否则就会出现各种各样的问题
在程序之中也是一样
有些对象我们只需要一个,比如工具类、线程池、缓存对象等等...
有些场景创建多个实例会导致一系列的问题,比如占用资源过多、运行结果达不到预期等...
特别是IO操作,轻则报错,重则损坏文件
使用单例模式可以有效解决上述问题,它能保证应用之中的某个实例有且只有一个
对于新手来说,单例模式也是一个面试会被经常问到的一个题
单例模式可分为两种实现方法:
- 饿汉模式
- 懒汉模式
饿汉模式
/**
* 单例模式
* 应用场景:保证应用之中的某个实例有且只有一个
*/
public class Singleton {
// 1、重写默认构造方法,将其私有化,不允许外部直接创建对象
private Singleton() {
}
// 2、创建类的唯一实例
private static Singleton instance = new Singleton();
// 3、提供一个用于获取实例的方法
public Singleton getInstance() {
return instance;
}
}
懒汉模式
/**
* 单例模式
* 应用场景:保证应用之中的某个实例有且只有一个
*/
public class Singleton {
// 1、重写默认构造方法,将其私有化,不允许外部直接创建对象
private Singleton() {
}
// 2、创建类的唯一实例
private static Singleton instance;
// 3、提供一个用于获取实例的方法
public Singleton getInstance() {
if (instance == null) {
instance = new Singleton();
}
return instance;
}
}
对比两个模式
在上面的代码中我们可以看到饿汉模式和懒汉模式在书写上其实没有什么明显的区别
但是实际运行时饿汉模式会在类被加载的时候就将唯一实例创建好,这种情况下虽然在启动时比较慢,但在程序调用对象时会很快,而且它是线程安全的
而懒汉模式因为在加载的时候没有创建对象,所以启动会比较快,但是在程序调用时比较慢,而它也不是线程安全的
为什么说饿汉模式是线程安全的呢?
因为在饿汉模式中,这个类在加载的时候就实例化了,就算thread1和thread2同时获取它,取到的是类加载时实例化的那个变量的值,所以说是线程安全的;
而懒汉式线程不安全,因为在某些并发情况有可能thread1在if(instance==null)判断为真时进入了if体里但又没开始实例化,而这时thread2也进来了,这样最终就会导致他们会创建多个实例