zoukankan      html  css  js  c++  java
  • 设计模式之——单例模式

    java语言里面有三种经典的设计模式:单例模式、工厂模式、代理模式。

    一、单例模式:

    单例模式所解决的问题是:保证一个类在内存中的对象唯一性。

    单例模式特点:

    1、一个类只实例化一个对象,保证对象唯一性

    2、构造器私有化

    3、必须自行创建这个实例

    4、必须向整个系统提供这个实例,即有一个public修饰的方法。

     

    单例模式有多中写法,其中饿汉式和懒汉式比较常用。

     一、饿汉式单例模式:(线程安全)

    1 public class SingelModel{
    2     private static SingelModel singel=new SingelModel();
    3     private SingelModel(){}
    4     public static SingelModel getInstance(){
    5         return singel;
    6     }
    7 }    

      饿汉式在类创建的同时就已经创建好一个静态的对象供系统使用,以后不再改变,所以天生是线程安全的。

    二、懒汉式单例模式:(非线程安全)

     1 public class SingelModel {
     2     private static SingelModel singel=null;
     3     private SingelModel(){}
     4     public static SingelModel getInstance(){
     5         if(singel=null){
     6             singel=new SingelModel();
     7         }
     8         return singel;
     9     }          
    10 }    
    SingelModel 通过将构造方法限定为private避免了类在外部被实例化,在同一个虚拟机范围内,SingelModel 的唯一实例只能通过getInstance()方法访问。

    但是以上懒汉式单例的实现没有考虑线程安全问题,它是线程不安全的,并发环境下很可能出现多个Singleton实例,要实现线程安全,有以下三种方式,都是对getInstance这个方法改造,保证了懒汉式单例的线程安全。



    二(一)、懒汉模式,在getInstance方法上加同步
     1 public class SingelModel{
     2     private static SingelModel singel=null;
     3     private SingelModel(){}
     4     public static syhcronized SingelModel getInstance(){
     5         if(singel==null){
     6             singel=new SingelModel();
     7         }
     8         return singel;
     9     }
    10 }    

     在方法调用上加了同步,虽然线程安全了,但是每次都要同步,会影响性能,毕竟99%的情况下是不需要同步的

    二(二)、懒汉模式,双重检查锁定
     1 public class SingelModel{
     2     private static SingelModel singel=null;
     3     private SingelModel(){}
     4     public static SingelModel getInstance(){
     5         if(singel==null){
     6             synchronized(SingelModel.class){
     7                 if(singel==null){
     8                     singel=new SingelModel();
     9                 }
    10             }
    11         }
    12         return singel;
    13     }
    14 }

     在getInstance中做了两次null检查,确保了只有第一次调用单例的时候才会做同步,这样也是线程安全的,同时避免了每次都同步的性能损耗。这两种懒汉式即实现了线程安全,又避免了同步带来的性能影响。




    饿汉式和懒汉式区别:
    饿汉式就是类一旦加载,就把单例初始化完成,保证了在调用getInstance()方法时单例已经存在。
    懒汉式就是比较懒,只有在调用getInstance()方法时才去初始化这个单例。

    关于线程安全:
    饿汉式时天生的线程安全,可以直接用于多线程而不用考虑会出现问题。
    懒汉式本身并不是线程安全的,为了安全才会有上面两种写法
    在getInstance方法上加同步,双重检查锁定

    关于资源加载和性能:
    饿汉式在类创建的同时就会实例化一个静态对象,之后不管用不用这个单例都会占据一定的内存,但相应的,第一次调用时速度会很快。
    而懒汉式顾名思义,会延迟加载,在第一次使用该单例的时候才会实例化对象出来,第一次调用时要做初始化,如果要做的工作比较多,性能上会有些延迟,之后就和饿汉式一样了。

     下面是一个双重检查锁定懒汉式单例模式例子:

     1 package singel;
     2 
     3 /*
     4  * 单例模式举例说明
     5  * 
     6  */
     7 public class TestMain {
     8     public static void main(String[] args) {
     9         SingelModel s1 = SingelModel.getSingel();
    10         s1.setAge(10);
    11         SingelModel s2 = SingelModel.getSingel();
    12         s2.setAge(20);
    13 
    14         s1.printinfo();
    15         s2.printinfo();
    16         
    17         System.out.println(s1==s2);
    18     }
    19 }
    20 
    21 class SingelModel {
    22     int age;
    23     private static SingelModel singelmodel = null;
    24 
    25     private SingelModel() {
    26     }
    27 
    28     public static SingelModel getSingel() {
    29         if (singelmodel == null) {
    30             synchronized (SingelModel.class) {
    31                 if (singelmodel == null) {
    32                     singelmodel = new SingelModel();
    33                 }
    34             }
    35         }
    36         return singelmodel;
    37     }
    38 
    39     public int getAge() {
    40         return age;
    41     }
    42 
    43     public void setAge(int age) {
    44         this.age = age;
    45     }
    46 
    47     public void printinfo() {
    48         System.out.println("age:" + age);
    49     }
    50 }

     运行结果:

     1 age:20

    2 age:20

    3 true 

  • 相关阅读:
    零基础学python-8.2 列表的基本操作、迭代和解析
    零基础学python-8.1 列表
    轻松python文本专题-字符串开头或者结尾匹配
    轻松python文本专题-maketrans和translate
    轻松python文本专题-字符串逐字符反转以及逐单词反转
    轻松python文本专题-拼接、合并字符串
    创建jsp+Servlet+JavaBean+JDBC+MySQL项目的过程
    request传递参数
    表单如何与Servlet控制器关联
    JSTL标签库
  • 原文地址:https://www.cnblogs.com/whx20100101/p/7455839.html
Copyright © 2011-2022 走看看