Java单例模式学习笔记

  Singleton 模式的宗旨在于确保某个类只有一个实例,别且为之提供一个全局访问点。为了防止其他工作人员实例化我们的类,

  可以为该类创建唯一一个构造器,并将构造器的可见设置为私有。值得注意的是,如果我们创建了其他的非私有的构造器,或者根本没有为该类提

  供构造器,那么其他人员还是能实例化我们的类。 如果不希望提前创建单例对象,我们可以等到第一次使用该单例对象的时候在创建它,即

  滞后初始化。滞后初始化单例对象有两个理由:

  1. 也许在静态初始化时间,你没有关于如何初始化单例对象的足够信息。

  2. 选择滞后初始化单例的目的也许为了等待资源,诸如数据库连接,尤其是在某些特定会话中不需要这个单例的应用程序中。

  如果在多线程环境中对单例采用滞后初始化,那么我们必须小心防止多个线程同时初始化该

  通常单例模式在Java语言中,有两种构建方式:

  懒汉方式:指全局的单例实例在第一次被使用时构建。延迟初始化。

  饿汉方式:指全局的单例实例在类装载时构建。 急切初始化。

  1、饿汉式单例类

  publicclassSingleton1{ privateSingleton1(){ } //在自己内部定义自己一个实例.//注意这是private只供内部调用privatestaticSingleton1instance=newSingleton1(); /***//***这里提供了一个供外部访问本class的静态方法,可以直接访问*@return*/publicstaticSingleton1getInstance(){ returninstance; } }

  2、懒汉式单例类

  publicclassSingleton2{ privatestaticSingleton2instance=null; /***//***这个方法比上面有所改进,不用每次都进行生成对象,只是第一次 *使用时生成实例,提高了效率!*@return*/publicstaticSingleton2getInstance(){ if(instance==null) instance=newSingleton2(); returninstance; } }

  下面主要多线程问题,在懒汉单例中,单线程是没有问题的,但多线程时就会有可能出现两个或者以上的Singletion2实例的情况。

  例如:线程1在判断instance==null为真,扫行new操作时,在执行new操作之前,判断为真之后,线程2正好执行判断操作,这时instance还为null.因此,线程2也会执行new操作。以此类推,在高并发下面,就可能存在两个或者以上的Singletion2的实例。显然,这是不正确的。

  因此改变代码如下:

  publicclassSingleton3{ privatestaticSingleton3instance=null; /***//** *这个方法比上面有所改进,不用每次都进行生成对象,只是第一次  *使用时生成实例,提高了效率! *为了多线程不出错,加入了同步标志 *@return */publicstaticsynchronizedSingleton3getInstance(){ if(instance==null) instance=newSingleton3(); returninstance; } }

  但这样又产生了一个问题,每次获取实例时方法都是同步的,显然性能很受影响的,所以继续更改代码如下:

  先记一下:volatile(网上抄的)

  volatile,用更低的代价替代同步

  为什么使用volatile比同步代价更低?

  同步的代价,主要由其覆盖范围决定,如果可以降低同步的覆盖范围,则可以大幅提升程序性能.

  而volatile的覆盖范围仅仅变量级别的。因此它的同步代价很低.

  volatile原理是什么?

  volatile的语义,其实是告诉处理器,不要将我放入工作内存,请直接在主存操作我.(工作内存详见java内存模型)

  因此,当多核或多线程在访问该变量时,都将直接操作主存,这从本质上,做到了变量共享。

  volatile的有什么优势?

  1、更大的程序吞吐量

  2、更少的代码实现多线程

  3、程序的伸缩性较好

  4、比较好理解,无需太高的学习成本

  volatile有什么劣势?

  1、容易出问题

  2、比较难设计

  volatile使用jdk要求1.5版本及1.5以上。

  改进后的代码如下(又叫双重加锁):

  publicclassSingleton4{ privatestaticvolatileSingleton4instance; /***//** *双重加锁实现多线程运用和性能优化 *@return */publicstaticSingleton4getInstance() { if(instance==null) { synchronized(Singleton4.class){//1 if(instance==null)//2 instance=newSingleton4();//3 } } returninstance; } }

  参考自第联网和head first设计模式。

记录沿途的心情。那样的生活才是我想要的。

Java单例模式学习笔记

相关文章:

你感兴趣的文章:

标签云: