单例模式 分析代码优化方法

单例模式是23种设计模式之一,是比较简单的一种设计模式,它的目的是无论调用多少次,都返回同一个对象,它的特点是构造器私有化。

  它分为两种结构,一种是懒汉式的,一种是饿汉式的,它们各有优缺点,我们先从饿汉式看起,代码如下:

public class Single {
  private static Single single = new Single();
  private Single() {
  }
   public Single getInstance() {
    return single;
  }
}

通过上面的程序可以看出来虽然我们加载同一个对象的目的确实达到了,但当程序被加载的时候就会创建single这个对象,当这个类有多个这样的方法时,我们可能会用不到这个对象中大多数单例,就会造成对内存的浪费。所以就出现了懒汉式的单例模式,代码如下:

public class Single {
  private static Single single = null;
  private Single() {
  } 

  public Single getInstance() {
    if(single==null){
      single = new Single();
    }
    return single;
  }
}

这样,只有当我们真正调用这个对象时它才会被new出来,但是这样是存在问题的。

  当上面的第二段代码在第一次加载的时候有两个线程对其进行了调用,则会产生两个不同的对象,所以是线程不安全的,这时候就会想到给这个方法加个锁,加锁之后的代码如下:

public class Single {
  private static Single single = null;
  private Single() {
  } 

  public synchronized Single getInstance() {
    if (single == null) {
      single = new Single();
    }
    return single;
  }
}

这样做确实做到了线程安全,但是当加锁这个方法里面要执行很多东西,调用这个方法花费的时间会很长,这样对服务器来说是致命的,因为这个方法如果某个线程一直调用的话,其它的线程是没有办法调的,服务器就阻塞了,那么升级后的代码如下:

public class Single {
  priate static Single single = null;
  private Single() {
  } 

  public Single getInstance() {
    if (single == null) {
      synchronized (Single.class) {
        single = new Single();
      }
    }
    return single;
  }
}

仔细观察以后发现这样并没有锁住,当第一次同时有两个线程到达getInstance()方法if判断时,其中有一个肯定是阻塞的,当另外一个执行完以后,阻塞这个线程是不会再判断是否为空的,还是会创建一个对象的,这样又有多个对象被产生了,再对其进行升级,得到的代码如下:

public class Single {
  private static Single single = null;
  private Single() {
  } 

  public Single getInstance() {
    if (single == null) {
      synchronized (Single.class) {
        if (single == null) {
          single = new Single();
        }
      }
    }
    return single;
  }
}

这样就不会产生上面的问题,而且也只锁一次,因为第二次再执行这个方法时,会跳过if判断,直接返回single,不会再被锁,执行效率也会很高。

  但即使是这样,也还是有问题的,因为我们不能确定在内存中是先给对象赋值,还是先创建了这个对象,所以第二个程序有可能得到的是初始化一半了的对象,在jdk1.5之后,我们可以用volatile这个关键字来避免这种情况,代码如下:

public class Single {
  private static volatile Single single = null;
  private Single() {
  } 

  public Single getInstance() {
    if (single == null) {
      synchronized (Single.class) {
        if (single == null) {
          single = new Single();
        }
      }
    }
    return single;
  }
}

但是这种情况很少使用,我在这里只是为了学习一下,嘻嘻

(0)

相关推荐

  • 单例模式 分析代码优化方法

    单例模式是23种设计模式之一,是比较简单的一种设计模式,它的目的是无论调用多少次,都返回同一个对象,它的特点是构造器私有化. 它分为两种结构,一种是懒汉式的,一种是饿汉式的,它们各有优缺点,我们先从饿汉式看起,代码如下: public class Single { private static Single single = new Single(); private Single() { } public Single getInstance() { return single; } } 通过

  • Java单例模式实现静态内部类方法示例

    Singleton是众多设计模式中最容易理解的一种,也是众多设计模式中较为重要的一种设计模式.接下来我们看看具体介绍. Singleton模式实现的重点在于将构造函数私有化(private),并通过提供静态公有函数(public synchronized static xxx getInstance)来获取定义在类中的静态私有成员(private static xxx instance),通过一个简单的判断静态实例是否为空来控制这个类只能够new一次,即控制了一个类只能有单个实例,一般的实现如下

  • pytorch多进程加速及代码优化方法

    目标:优化代码,利用多进程,进行近实时预处理.网络预测及后处理: 本人尝试了pytorch的multiprocessing,进行多进程同步处理以上任务. from torch.multiprocessing import Pool,Manager 为了进行各进程间的通信,使用Queue,作为数据传输载体. manager = Manager() input_queue = manager.Queue() output_queue = manager.Queue() show_queue = ma

  • java单例模式实现的方法

    1.最基本的单例模式 /** * @author LearnAndGet * @time 2018年11月13日 * 最基本的单例模式 */public class SingletonV1 { private static SingletonV1 instance = new SingletonV1();; //构造函数私有化 private SingletonV1() {} public static SingletonV1 getInstance() { return instance; }

  • c# 单例模式的实现方法

    单例模式大概是所有设计模式中最简单的一种,如果在面试时被问及熟悉哪些设计模式,你可能第一个答的就是单例模式. 单例模式的实现分为两种:饿汉式和懒汉式.前者是在静态构造函数执行时就立即实例化,后者是在程序执行过程中第一次需要时再实例化.两者有各自适用的场景,实现方式也都很简单,唯一在设计时要考虑的一个问题就是:实例化时需要保证线程安全. 饿汉式 饿汉式实现很简单,在静态构造函数中立即进行实例化: public class Singleton { private static readonly Si

  • 全面分析Java方法的使用与递归

    目录 java中方法的使用 什么是方法 方法的定义与使用 方法如何进行调用及其方法调用过程 方法的形参和实参 方法重载 方法签名 递归 java中方法的使用 什么是方法 举一个日常生活中的例子,比如我们在学校班长都会发送消息,比如它想让班级里的每一个人到某某教学楼某某班级进行开会,他就会给每个人发信息,同学今天我们有重要会议要进行开班会请你到某某教学楼某某班级来,如果班长要给每一个人发送信息,一个班里有很多人这样班长发信息就会很累,换个思路,班长要群发消息这样是不就会很省心.这也就是与java中

  • Android Fragment源码分析Add方法

    目录 前言 Add() 前言 本篇我们就来讲讲Fragment管理中的 Add() 方法 Add() 在我们动态的添加.管理Fragment中,Add属于最基础的方法了: 用法也很简单,如下就是向Activity添加一个Fragment: getSupportFragmentManager().beginTransaction().add(R.id.fragmenta,new FragmentA()).commit(); 一般时候我们使用到Fragment的时候,都是不止一个,比如微信界面,底部

  • Python 中单例模式的实现方法

    单例 — 让 类 创建的对象,在系统中 只有唯一的一个实例: 1).定义一个类属性,初始值是 None ,用于记录 单例对象的引用: 2).重写 new 方法: 3).如果 类属性 is None,调用父类方法分配空间,并在类属性中记录结果: 4).返回 类属性 中记录的 对象引用: class MusicPlayer(object): # 记录第一个被创建对象的引用 instance = None def __new__(cls, *args, **kwargs): # 判断类属性是否是空对象

  • linux磁盘管理软RAID的实现原理分析和方法分享

    1 什么是RAID RAID全称是独立磁盘冗余阵列(Redundant Array of Independent Disks),基本思想是把多个磁盘组合起来,组合一个磁盘阵列组,使得性能大幅提高. RAID分为几个不同的等级,各个不同的等级均在数据可靠性及读写性能做了不同的权衡.实际工作中根据自己的业务需求选择不同的RAID方案. 2 RAID的实现方式 外接式磁盘阵列:通过扩展卡提供适配能力内接式RAID:主板集成RAID控制器安装OS前在BIOS里配置软件RAID:通过OS实现 3 标准的R

  • Java单例模式分析

    目录 单例模式 为什么要用单例 单例的关键点 几种写法 懒汉式 饿汉式 静态内部类写法 枚举单例 容器实现单例 参考 总结 单例模式 为什么要用单例 确保某个类只有一个对象,常用于访问数据库操作,服务的配置文件等. 单例的关键点 1.默认构造函数为private,复制构造函数和复制赋值函数也要private或=delete禁用.(做到无法被外部其他对象构造) 2.通过一个静态方法或枚举返回单例类对象. 3.确保多线程的环境下,单例类对象只有一个. 几种写法 本文主要介绍C++的懒汉式和饿汉式写法

随机推荐