码迷,mamicode.com
首页 > 编程语言 > 详细

java常用设计模式-单例模式

时间:2017-02-14 15:24:55      阅读:294      评论:0      收藏:0      [点我收藏+]

标签:vp9   c51   iat   oat   bvs   owb   fbi   实例化   singleton   

java设计模式系列之单例模式

单例模式定义

      一个类有且仅有一个实例,并且自行实例化向整个系统提供。

单例模式作用

      简单来说,就是在整个程序运行的生命期中,任何一个时刻,单例类的实例都只有一个(当然也可以一个都没有)。

如何保证对象的唯一性

      思想:(1)不让其他程序创建该类对象;

               (2)在本类中创建该类对象;

               (3)创建一个对外提供的方法,可以让其他类进行调用。

      步骤:(1)因为创建对象的时候都要初始化构造函数,将该类的构造函数私有化,其他程序就无法再创建该类对象;

               (2)就是在本类中创建本类对象;

               (3)定义一个方法,返回该类对象,让其他类可以调用此方法(作用:可控,对象的由自己决定,不能谁想new就new)。

我们直接在类中自己创建一个对象,getSingle方法只负责把对象返回给调用者,实现单例可控(你能获取我的方法,但能拿到的是我自己创建的对象)

技术分享

代码体现方式:

      (1)私有化构造函数        (2)创建私有并静态的本类的对象         (3)创建公有的静态的调用方法,返回该对象

代码实现主要有两种方式:饿汉模式和饱汉模式

饿汉模式:类加载的时候对象就已经存在了内存中,是线程安全的,在类创建好的同时竟已经创建好了一个静态的对象供系统使用,以后不再改变。(为什么是线程安全的,后面给出解释)

技术分享

 

懒汉模式:类加载的时候对象还不存在,就是所谓的延迟加载方式,需要时再创建对象,此模式如果在创建对象时不加上synchronized则会导致对对象的访问不是线程安全的(为啥不是线程安全的,后面解释)

技术分享

下面解释一下,懒汉式的线程不安全性,通常情况下,我们建议写饿汉式,因为它是线程安全的

当线程访问懒汉式时,懒汉式的方法会对共性数据进行多条语句的操作

技术分享

两个线程,线程1和线程2,当线程1执行到sin为null,还没创建对象时,线程2也执行到sin为null并且创建了对象,此时,两个线程就会创建两个对象,违背了单例模式的原则。

 

出现线程安全的问题,为了解决这种问题,加入同步机制(不熟悉同步机制请百度):静态同步函数的锁是类的字节码文件对象

技术分享

 这样一种设计可以保证只产生一个实例,并且只会在初始化的时候加同步锁,看似精妙绝伦,但却会引发另一个问题,这个问题由指令重排序引起。(这一部分来自:http://blog.csdn.net/zhangzeyuaaa/article/details/42673245)

 

指令重排序是为了优化指令,提高程序运行效率。指令重排序包括编译器重排序和运行时重排序。JVM规范规定,指令重排序可以在不影响单线程程序执行结果前提下进行。例如 instance = new Singleton() 可分解为如下伪代码:

 

memory = allocate();   //1:分配对象的内存空间
ctorInstance(memory);  //2:初始化对象
instance = memory;     //3:设置instance指向刚分配的内存地址

 

但是经过重排序后如下:

 

memory = allocate();   //1:分配对象的内存空间
instance = memory;     //3:设置instance指向刚分配的内存地址
                       //注意,此时对象还没有被初始化!
ctorInstance(memory);  //2:初始化对象

 

将第2步和第3步调换顺序,在单线程情况下不会影响程序执行的结果,但是在多线程情况下就不一样了。线程A执行了instance = memory(这对另一个线程B来说是可见的),此时线程B执行外层 if (instance == null),发现instance不为空,随即返回,但是得到的却是未被完全初始化的实例,在使用的时候必定会有风险,这正是双重检查锁定的问题所在!

 

在JDK1.5之后,可以使用volatile变量禁止指令重排序:

 

代码实现:

技术分享

 

 

本博客的转载之处:http://www.cnblogs.com/ysw-go/

 

java常用设计模式-单例模式

标签:vp9   c51   iat   oat   bvs   owb   fbi   实例化   singleton   

原文地址:http://www.cnblogs.com/zhang-na/p/6397543.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!