zoukankan      html  css  js  c++  java
  • 单例模式--笔记

    单例模式是一种对象创建型模式,使用单例模式,可以保证一个类只能唯一的生成一个实例化对象

    GoF对单例模式的定义:保证在一个类中,只有一个实例存在,同时提供能对该实例加以访问的全局访问方法。

    在应用开发系统中,我们常常需要以下需求:

    1).在多线程之间,如servlet环境,共享同一个资源或者操作同一个对象

    2).在整个程序空间启用全局变量,共享资源

    3).大规模系统中,为了性能的考虑,需要节省对象的创建时间等等

    因为Singleton模式可以保证为一个类只生成唯一的一个实例对象,所以对于上述情况,Singleton模式就派上用场了。

    单例模式实现:

    1.饿汉式;

    2.懒汉式;

    3.双重检查

    一般实现:

     1 public class Person{
     2    
     3     priate String name;
     4    
     5     public String getName(){
     6      
     7       return name;
     8      } 
     9     public String setName(){
    10      
    11       return this.name=name;
    12      } 
    13    
    14    
    15    }

    主类:

     1 public class MainClass{
     2   public static void main(String[] args){
     3     
     4     Person per=new Person();
     5     Person per2=new Person();
     6     //定义变量
     7     per.setName("张三");
     8     per2.setName(“李四”);
     9     //通过person类生成了两个对象
    10     System.out.println(per.getName());
    11     System.out.println(per2.getName());
    12 
    13   }
    14 }

    此时,在非单例模式下,定义两个对象,得到了输出结果为:

    张三

    李四

    首先展示的是饿汉式:

     1 public class Person{
     2    
     3     priate String name;
     4     public static final Person person =new person();//饿汉式设置
     5      //
     6     public String getName(){
     7      
     8       return name;
     9      } 
    10     public String setName(){
    11      
    12       return this.name=name;
    13      } 
    14     //构造函数私有化
    15     private person(){
    16    
    17    }
    18    //构造一个全局的静态方法:因为如果不是全局的,那么需要通过对象来进行调用,如果定义成全局的静态,就可以通过类来调用
    19    public static Person getPerson(){
    20      return new Person();
    21       }
    22    }

    此时,对于主类修改为:

     1 public class MainClass{
     2     public static void main(String[] args){
     3     Person per=Person.getPerson();//不再使用new来定义对象,用类定义
     4     Person per2=Person.getPerson();
     5      //定义变量
     6      per.setName("张三");
     7      per2.setName("李四");
     8     //通过person类生成了两个对象
     9      System.out.println(per.getName());
    10      System.out.println(per2.getName());
    11  
    12    }
    13  }

    得到的结果为:

    李四

    李四

    懒汉式:

     1 public class Person{
     2     
     3    priate String name;
     4     private static Person person;//静态初始化默认为null
     5      public String getName(){
     6       return name;
     7       } 
     8     public String setName(){
     9       
    10        return this.name=name;
    11       } 
    12      //构造函数私有化
    13      private person(){    
    14     }
    15     public static Person getPerson(){
    16     //此处添加一个判断
    17      if(person==null)   person=new  Person;     
    18       return  person();
    19        }
    20     }

    结果为:

    李四

    李四

    上述两种情形各有所长,在饿汉式中,一加载Person类就进行初始化对象,保证同一个对象

    在上述懒汉式中,可以保证单线程正常单例模式

    允许多线程的懒汉式单例模式:

     1 public class Person{
     2    
     3     priate String name;
     4     private static Person person;//静态初始化默认为null
     5       public String getName(){
     6        return name;
     7        } 
     8     public String setName(){
     9       
    10         return this.name=name;
    11       } 
    12       //构造函数私有化
    13       private person(){    
    14      }
    15     //使用一个全局的静态方法,使用同步方式
    16      public static Synchrogazed Person getPerson(){
    17     //当有一个线程进来时,这个方法就被霸占了,对于进来的方法就是将执行完毕在允许其他线程进入
    18       if(person==null)  //第一步
    19          person=new  Person;  //   第二步
    20        return  person();//第三步  
    21        }
    22      }

    双重检查:

      原因:在上述的多线程代码段中,我们实现的是将整个方法都实现同步,

     经过思考,我们可以发现,对于只有第一次的时候才会执行if内的内容;整个方法锁死后,接下来第二次,第三次。。。进来的都要进行判断if语句,影响执行效率

     1   public class Person{
     2      
     3       priate String name;
     4       private static Person person;//静态初始化默认为null
     5         public String getName(){
     6          return name;
     7          } 
     8       public String setName(){
     9         
    10          return this.name=name;
    11        } 
    12        //构造函数私有化
    13        private person(){    
    14       }
    15      //使用一个全局的静态方法
    16       public static  Person getPerson(){
    17      //当有一个线程进来时,这个方法就被霸占了,对于进来的方法就是将执行完毕在允许其他线程进入
    18        if(person==null) { //第一步
    19           Synchrogazed(Person.class){//仅仅同步化这一部分
    20           if(person==null)//这个判断语句添加的原因 当有两个线程进来时,第一个线程和第二个线程都执行完 
    // if(person==null)这条语句,第一个线程进入同步,第二个线程等待,当第一个线程执行完,
    //return之后,第二个线程又会执行同步语句,及时第一个线程已经new了一个对象,所以为防止这个情况的发生,
    //需要在同步里边再判断一次,也就是第二次判断
    21 person=new Person();} 22 } // 第二步 23 return person();//第三步 24 } 25 }
  • 相关阅读:
    删除ubuntu多余内核
    Linux从入门到精通(第8章--磁盘管理)
    图书销售管理系统概要设计,系统数据结构设计分工
    图书管理销售系统,出错设计部分
    图书管理销售系统概要分析,接口设计部分
    图书管理销售系统,运行设计部分
    图书管理销售管理系统,总体设计部分
    图书销售管理概要分析报告,引言部分
    图书销售管理系统概要分析报告总体分工
    图书销售管理系统需求分析,各种功能图部分
  • 原文地址:https://www.cnblogs.com/lujun1949/p/5721174.html
Copyright © 2011-2022 走看看