html5中文学习网

您的位置: 首页 > 网络编程 > java教程 » 正文

java 设计模型之单例模式详解_java_

[ ] 已经帮助:人解决问题

Singleton 模式的宗旨在于确保某个类只有一个实例,别且为之提供一个全局访问点。为了防止其他工作人员实例化我们的类,32EHTML5中文学习网 - HTML5先行者学习网

可以为该类创建唯一一个构造器,并将构造器的可见设置为私有。值得注意的是,如果我们创建了其他的非私有的构造器,或者根本没有为该类提32EHTML5中文学习网 - HTML5先行者学习网

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

滞后初始化。滞后初始化单例对象有两个理由:32EHTML5中文学习网 - HTML5先行者学习网

1.也许在静态初始化时间,你没有关于如何初始化单例对象的足够信息。32EHTML5中文学习网 - HTML5先行者学习网

2.选择滞后初始化单例的目的也许为了等待资源,诸如数据库连接,尤其是在某些特定会话中不需要这个单例的应用程序中。32EHTML5中文学习网 - HTML5先行者学习网
  如果在多线程环境中对单例采用滞后初始化,那么我们必须小心防止多个线程同时初始化该
32EHTML5中文学习网 - HTML5先行者学习网

通常单例模式在Java语言中,有两种构建方式:32EHTML5中文学习网 - HTML5先行者学习网

懒汉方式:指全局的单例实例在第一次被使用时构建。延迟初始化。 32EHTML5中文学习网 - HTML5先行者学习网
32EHTML5中文学习网 - HTML5先行者学习网

饿汉方式:指全局的单例实例在类装载时构建。 急切初始化。32EHTML5中文学习网 - HTML5先行者学习网

1,饿汉式单例类32EHTML5中文学习网 - HTML5先行者学习网

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

2,懒汉式单例类32EHTML5中文学习网 - HTML5先行者学习网

public class Singleton2 { private static Singleton2 instance = null; /** *//** * 这个方法比上面有所改进,不用每次都进行生成对象,只是第一次    * 使用时生成实例,提高了效率! * @return */ public static Singleton2 getInstance() {  if (instance == null) instance = new Singleton2(); return instance; }}
32EHTML5中文学习网 - HTML5先行者学习网

32EHTML5中文学习网 - HTML5先行者学习网

下面主要多线程问题,在懒汉单例中,单线程是没有问题的,但多线程时就会有可能出现两个或者以上的Singletion2实例的情况。32EHTML5中文学习网 - HTML5先行者学习网

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

因此改变代码如下:32EHTML5中文学习网 - HTML5先行者学习网

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

但这样又产生了一个问题,每次获取实例时方法都是同步的,显然性能很受影响的,所以继续更改代码如下:32EHTML5中文学习网 - HTML5先行者学习网

 volatile, 用更低的代价替代同步32EHTML5中文学习网 - HTML5先行者学习网

 为什么使用volatile比同步代价更低?32EHTML5中文学习网 - HTML5先行者学习网
同步的代价, 主要由其覆盖范围决定, 如果可以降低同步的覆盖范围, 则可以大幅提升程序性能.32EHTML5中文学习网 - HTML5先行者学习网

而volatile的覆盖范围仅仅变量级别的. 因此它的同步代价很低.32EHTML5中文学习网 - HTML5先行者学习网

volatile原理是什么?32EHTML5中文学习网 - HTML5先行者学习网

volatile的语义, 其实是告诉处理器, 不要将我放入工作内存, 请直接在主存操作我.(工作内存详见java内存模型)32EHTML5中文学习网 - HTML5先行者学习网

因此, 当多核或多线程在访问该变量时, 都将直接操作主存, 这从本质上, 做到了变量共享.32EHTML5中文学习网 - HTML5先行者学习网

32EHTML5中文学习网 - HTML5先行者学习网

volatile的有什么优势?32EHTML5中文学习网 - HTML5先行者学习网
1, 更大的程序吞吐量32EHTML5中文学习网 - HTML5先行者学习网
2, 更少的代码实现多线程32EHTML5中文学习网 - HTML5先行者学习网
3, 程序的伸缩性较好32EHTML5中文学习网 - HTML5先行者学习网
4, 比较好理解, 无需太高的学习成本
32EHTML5中文学习网 - HTML5先行者学习网

volatile有什么劣势?32EHTML5中文学习网 - HTML5先行者学习网
1, 容易出问题32EHTML5中文学习网 - HTML5先行者学习网
2, 比较难设计
32EHTML5中文学习网 - HTML5先行者学习网

volatile使用jdk要求1.5版本及1.5以上。32EHTML5中文学习网 - HTML5先行者学习网

改进后的代码如下(又叫双重加锁):32EHTML5中文学习网 - HTML5先行者学习网
32EHTML5中文学习网 - HTML5先行者学习网

public class Singleton4 { private static volatile Singleton4 instance; /** *//** * 双重加锁实现多线程运用和性能优化 * @return */ public static Singleton4 getInstance() { if (instance == null) { synchronized(Singleton4.class) { //1 if (instance == null) //2 instance = new Singleton4(); //3 } } return instance; }}

32EHTML5中文学习网 - HTML5先行者学习网

(责任编辑:)
推荐书籍
推荐资讯
关于HTML5先行者 - 联系我们 - 广告服务 - 友情链接 - 网站地图 - 版权声明 - 人才招聘 - 帮助