vlambda博客
学习文章列表

始终如一--单例模式分析总结

定义

   顾名思议,单例,单一实例,就是在程序运行期间确保某一个类只有一个实例,一般称其为Singleton类。

实现方法

  既然只能有一个实例,那么肯定不能让程序运行期间随时都能new出一个实例,所以将构造函数私有化,通过在类内部自行实例化一个对象,并且通过getInstance()方法,向外部提供这个实例。

通用代码

  “饿汉式”单例,即不管之后是否能用的上此实例,在初始化类的时候就实例化对象,显得很“饥饿”

  此方法线程安全

public class Singleton { private static final Singleton singleton = new Singleton();
private Singleton(){};
//通过此方法获取唯一实例 public static Singleton getSingleton() { return singleton; }
//类中其他方法 public static void doSomething() { }}

  

“懒汉式”单例,在最开始不实例化对象,到后期运行需要时再实例化并返回,显得很“懒”

  为了实现懒汉式的线程安全,需要加锁

public class Singleton { private static Singleton singleton = null;
private Singleton(){};
//通过此方法获取唯一实例  //如果是单线程,不需要加锁,多线程则需要  public static synchronized Singleton getSingleton() { if (singleton == null) { singleton = new Singleton(); } return singleton; }
//类中其他方法 public static void doSomething() { }}

  为什么需要加锁?

  在高并发的情况下,假如线程A执行到了singleton = new Singleton(),但是因为对象还在初始化,所以还没有获取对象,在此期间,线程B执行到singleton == null,此时判定为真,那么线程B也会去实例化对象,造成内存中出现了两个实例,所以多线程情况下需要加锁。


优缺点

  优点

    1. 减少内存开支

    2.减少系统性能开销

    3.避免对资源的多重占用

    4.优化和资源共享访问

  缺点

    1.一般没有接口,扩展困难

    2.对测试不友好,在并行开发中,如果单例模式没有完成,不能进行测试

    3.与单一职责原则冲突,单例模式“单例”和业务逻辑融合在了一个类中

使用场景

  1.要求生成唯一序列号的环境

  2.整个项目共享的访问点或者数据

  3.需要定义大量的静态变量和静态方法的环境,此时也可以直接声明为static  

  

点击下方“阅读原文”,进入我的博客