一、什么是单例模式?
1、单例模式就是保证在应用该模式的类只有一个实例,适用于只需要一个实例的类。
二、单例模式特点?
1、构造函数私有化。
2、定义静态方法返回当前对象
3、确保只有一个对象(单例模式的几种实现方式)
4、确保在序列化和反序列化后保证是同一个对象
三、单例模式的几种实现?
1) 饿汉式——不管你用不用,我都提前准备好实例
优点: 安全( 比如线程安全),能确保只创建一个对象
缺点: 耗内存, instance在类装载时就实例化,虽然导致类装载的原因有很多种,在单例模式中大多数都是调用getInstance方法, 但是也不能确定有其他的方式(或者其他的静态方法)导致类装载
案例: 18960623520
public class Singleton {
//传参数没法做
private static Singleton instance =new Singleton();
private Singleton() {
}
public static Singleton getInstace() {
return instance;
}
}
2) 懒汉式—— 当你要使用的时候,实例化对象 (一般开发中都使用这种模式)
优点: 性能高
缺点: 需要使用额外的方式保证只有一个对象(需要保证线程安全),存在并发问题
案例:
public class Singleton {
private static Singleton instance; // 静态成员变量
private Singleton() { // 私有构造函数
}
//在服务器,或者多线程访问
//服务器并发
public static Singleton getInstace() {
//假设:3个线程---并发线程
//场景:同时调用getInstace方法
//线程一:
if (instance ==null) {
instance =new Singleton();
}
return instance;
}
}
3)懒汉式——线程同步,针对懒汉式做优化
优点: 线程同步,保证对象的唯一
缺点: 99%的情况下不需要同步,影响性能
案例:public class Singleton {
private static Singleton instance; // 静态成员变量
private Singleton() { // 私有构造函数
}
public static synchronized Singleton getInstace() { // 方法加锁,保证了线程安全,但是在99%的场景下,使用的时候都不需要多线程控制,导致加锁影响了性能。
if (instance ==null) {
instance =new Singleton();
}
return instance;
}
}
4)懒汉式——针对同步进一步优化,双重检查
优点: 保证了线程安全,同时效率也相对较高
缺点:还是影响了部分的性能。
/**
* 双重检查(折中考虑,既不浪费内存,性能相对来说也比较高)*
*/
public class Singleton {
//线程并发时候,当我们的变量被被修改之后,其他的并发线程及时收到通知,其他的线程就可以访问数据
//volatile--会屏蔽虚拟机优化过程
private volatile static Singleton instance;
private Singleton() {
}
public static Singleton getInstace() {
if(instance ==null){
synchronized (Singleton.class) {
if(instance ==null){
instance =new Singleton();
}
}
}
return instance;
}
}
5)静态内部类
优点: 保证只有一个对象,线程安全
public class Singleton {
private static class SingletonHolder{
private static Singleton singleton =new Singleton();
}
public static Singleton getInstance(){
return SingletonHolder.singleton;
}
}
6) 枚举方法——不常用,能避免多线程同步问题,而且还能防止反序列化重新创建新的对象。
public enum Singleton {
INSTANCE;
public void whateverMethod() {
}
}
四、总结
1、当然除了以上几种单例模式设计外,还有其他一些不常用的,比如通过hashmap来保证实例的唯一性,这就不做说明了
2、如果选择?
个人觉得,并没有绝对选择哪种单例模式,主要看场景?
1、如果是对安全性要求不高,性能要求高可以使用 2) 懒汉式—— 当你要使用的时候,实例化对象 (一般开发中都使用这种模式)
2、如果对安全性,性能要求也较高,可以使用双重检查这种 4)懒汉式——针对同步进一步优化,双重检查*** 个人推荐项目中用这种
代码参考: https://github.com/zhenqinrui/architecture