【Java面试指北】单例模式

打印 上一主题 下一主题

主题 888|帖子 888|积分 2664

单线程下的单例模式:
  1. public class Singleton {
  2.     private static Singleton instance;
  3.     private Singleton() {}
  4.     public static Singleton getInstance() {
  5.         if (instance == null) {
  6.             instance = new Singleton()
  7.         }
  8.         return instance;
  9.     }
  10. }
复制代码
几个关键点:

  • static 修饰:表名属于类而不是类对象,不会每生成一个新的类对象都新生成一份。而且可以在不创建类对象的情况下直接调用。
  • 为什么构造函数是private 类型?不然呢,开放了构造函数还怎么单例。
  • 为什么不把单例的逻辑放到构造函数中?在 Singleton() 中调用 Singleton() 么,那不是死循环了。
  • 类中的单例变量是 private 类型的,不能直接访问,要通过 getInstance() 来获取。
多线程下的单例模式:

和单线程有什么区别?

  • 需要考虑线程安全问题
  • 需要考虑服从问题
方法一:
只需要给 getInstance 方法添加 synchronized 关键字即可。
  1. public static synchronized Singleton getInstance() {
复制代码
问题:每次访问都要同步,会降低性能。
方法二:
双重查抄锁定
  1. public class Singleton {
  2.     private static volatile Singleton instance;
  3.     private Singleton() {}
  4.     public static Singleton getInstance() {
  5.         if (instance == null) {
  6.             synchronized (Singleton.class) {
  7.                 if (instance == null) {
  8.                     instance = new Singleton()
  9.                 }
  10.             }
  11.         }
  12.         return instance;
  13.     }
  14. }
复制代码
关键点:

  • 性能优化:将 synchronized 放到现实创建时,只有第一次实例未创建才会同步,后续都不会。
  • 为什么要双重查抄 instance==null?第一次查抄完,有可能被别的线程先创建了。
  • 为什么 instance 要用 volatile 修饰?

    • 由于 new Singleton() 不是一个单一的操作,会存在指令重排的问题。
    • 1、为 instance 分配内存空间。2、初始化 instance。3、将 instance 指向分配的内存地点。
    • 假如指令重拍后,变为了 1-3-2,那么其他线程可能会拿到一个还没初始化的 instance。

  • 为什么有了 volatile 还需要 synchronized?

    • 由于 volatile 不保证原子性。


免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。
回复

使用道具 举报

0 个回复

倒序浏览

快速回复

您需要登录后才可以回帖 登录 or 立即注册

本版积分规则

天空闲话

金牌会员
这个人很懒什么都没写!

标签云

快速回复 返回顶部 返回列表