设计模式

来源:互联网 发布:专升本c语言考试大纲 编辑:程序博客网 时间:2024/05/21 10:51

设计模式之单利

 

        单利设计模式是非常常用的一种设计模式,也是提高效率的一种设计思路。单利其实还是很发杂的。

 

很多朋友其实早就接触了单利只是没有留意而已,  Servlet 就是一个单实例多线程的,所以Servlet存在线程安全

 

问题! 今天和大家分享一下单利的原理。

 

一.饿汉式单利

     现在很多程序员不关心JAVA的内存分配,以为JVM都可以搞定那么这是错误的。如果你对内存分配不是很在行还是要

 

了解一下,单利和内存分配,多线程是密不可分的。   饿汉式是比较简单, 看代码。

/*饿汉式单利设计模式*/class Singleten_ehanshi{private static Singleten_ehanshi s = new Singleten_ehanshi();private Singleten_ehanshi(){}public static Singleten_ehanshi getInstance(){return s;}}


 

为什么说单利可以提高效率但有线程安全问题?

当JVM通过类加载器加载类的时候Static并没有分配在堆内存上,而是在静态区(这是还没有类实例加载)。

这样保证了一个实例在内存中不会有多余的实例分配在堆内存中,所以效率会高一些。既然是Static的实例那么所有线程过来

多可以修改公共的东西(成员)所以安全性有问题,这和Servlet一样的问题。

 

二.懒汉式单利

 

/*单利设计模式:  懒汉式。多线程的问题解决.*/class  Singleten_lanhanshi{private static Singleten_lanhanshi sgl = null;private Singleten_lanhanshi(){}public static Singleten_lanhanshi getInstace(){if(sgl == null)  //减少锁的判断次数.{//这时候同步使用的是  字节码这个锁synchronized(Singleten_lanhanshi.class){if(sgl == null){sgl = new Singleten_lanhanshi();}}}return sgl;}public static void main(String[] args) {System.out.println("Hello World!");}}


 

大家可能对程序中为什么加一把锁而疑惑,这是懒汉式中比较重要的东西,多线程的问题就是由此而引起的。

我们来解释下这段代码

                if(sgl == null)  //减少锁的判断次数.{//这时候同步使用的是  字节码这个锁synchronized(Singleten_lanhanshi.class){if(sgl == null){sgl = new Singleten_lanhanshi();}}}


 

 

大家对于第一个应该明白,就是为了减少线程对锁的判断次数。

 

为什么要加一把锁?我们用多线程来推理, 当地一个线程判断了实例为空后可能会成为等待状态(或冻结)如图

第二个线程进来加了一把锁,并且对静态区的对象实例化,注意这时候对象已经不为空了。

这线程一醒了他还停留在对象为空的时候,又去实例化了一次这就出现了错误,所以必须同步。

 

同步为什么用这样的锁而不是对象锁呢?

这就是内存分配了,   大家想想当类加载的时候Static的先于对象被加载进内存,这个时候内存中还没有任何对象所以对象

锁是不可能的, 但是静态区中有这个静态对象本身所以要用这把锁。