zoukankan      html  css  js  c++  java
  • (三)单例模式

    这个模式是很有意思,而且比较简单,但是我还是要说因为它使用的是如此的广泛,如此的有人缘,单例就是单一、独苗的意思,那什么是独一份呢?你的思维是独一份,除此之外还有什么不能山寨的呢?我们举个比较难复制的对象:皇帝 

    中国的历史上很少出现两个皇帝并存的时期,是有,但不多,那我们就认为皇帝是个单例模式,在这个场景中,有皇帝,有大臣,大臣是天天要上朝参见皇帝的,今天参拜的皇帝应该和昨天、前天的一样(过渡期的不考虑,别找茬哦) ,大臣磕完头,抬头一看,嗨,还是昨天那个皇帝,单例模式,绝对的单例模式,先看类图: 





    然后我们看程序实现,先定一个皇帝: 


    package com.cbf4life.singleton1; 
     
    /** 
     * @author cbf4Life cbf4life@126.com 
     * I'm glad to share my knowledge with you all. 
     * 中国的历史上一般都是一个朝代一个皇帝,有两个皇帝的话,必然要PK出一个皇帝出来 
     */ 
    public class Emperor { 
      private static Emperor emperor = null;  //定义一个皇帝放在那里,然后给这个皇帝名字 
      
      private Emperor(){ 
       //世俗和道德约束你,目的就是不让你产生第二个皇帝 
     } 
      public static Emperor getInstance(){ 
       if(emperor == null){  //如果皇帝还没有定义,那就定一个 
        emperor = new Emperor(); 
      } 
       return emperor; 
     } 
      
      //皇帝叫什么名字呀 
      public static void emperorInfo(){ 
      System.out.println("我就是皇帝某某某....");    
     } 

    然后定义大臣: 


    package com.cbf4life.singleton1; 
     
    /** 
     * @author cbf4Life cbf4life@126.com 
     * I'm glad to share my knowledge with you all. 
     * 大臣是天天要面见皇帝,今天见的皇帝和昨天的,前天不一样那就出问题了! 
     */ 
    @SuppressWarnings("all") 
    public class Minister { 
     
      /** 
      * @param args 
      */ 
      public static void main(String[] args) { 
       //第一天 
        Emperor  emperor1=Emperor.getInstance(); 
      emperor1.emperorInfo();  //第一天见的皇帝叫什么名字呢? 
       
       //第二天 
        Emperor  emperor2=Emperor.getInstance(); 
      Emperor.emperorInfo(); 
       
       //第三天 
        Emperor  emperor3=Emperor.getInstance(); 
      emperor2.emperorInfo();  
       
       //三天见的皇帝都是同一个人,荣幸吧! 
     } 
     



    看到没,大臣天天见到的都是同一个皇帝,不会产生错乱情况,反正都是一个皇帝,是好是坏就这一
    个,只要提到皇帝,大家都知道指的是谁,清晰,而又明确。问题是这是通常情况,还有个例的,如同一
    个时期同一个朝代有两个皇帝,怎么办? 
     
    单例模式很简单,就是在构造函数中多了加一个构造函数,访问权限是 private 的就可以了,这个模
    式是简单,但是简单中透着风险,风险?什么风险?在一个 B/S 项目中,每个 HTTP Request 请求到 


    J2EE
    的容器上后都创建了一个线程,每个线程都要创建同一个单例对象,怎么办?,好,我们写一个通用的单例程
    序,然后分析一下: 
     
    package com.cbf4life.singleton3; 
     
    /** 
     * @author cbf4Life cbf4life@126.com 
     * I'm glad to share my knowledge with you all. 
     * 通用单例模式 
     */ 
    @SuppressWarnings("all") 
    public class SingletonPattern { 
      private static SingletonPattern singletonPattern= null; 
      //限制住不能直接产生一个实例 
      private SingletonPattern(){ 
       
     } 
      
      public SingletonPattern getInstance(){ 
       if(this.singletonPattern == null){  //如果还没有实例,则创建一个 
        this.singletonPattern = new SingletonPattern(); 
      }    
       return this.singletonPattern; 
     } 
      

     
    我们来看黄色的那一部分,假如现在有两个线程 A 和线程B,线程 A 执行到 this.singletonPattern  = w SingletonPattern(),正在申请内存分配,可能需要 0.001 微秒,就在这 0.001 微秒之内,线程 B 执行到 if(this.singletonPattern == null),你说这个时候这个判断条件是 true 还是 false?是 true,那然后呢?线程B也往下走, 于是乎就在内存中就有两个SingletonPattern的实例了, 看看是不是出问题了?
    如果你这个单例是去拿一个序列号或者创建一个信号资源的时候,会怎么样?业务逻辑混乱!数据一致性校验失败!最重要的是你从代码上还看不出什么问题,这才是最要命的!因为这种情况基本上你是重现不了的,不寒而栗吧,那怎么修改?有很多种方案,我就说一种,能简单的、彻底解决问题的方案: 
     
    package com.cbf4life.singleton3; 
     
    /** 
     * @author cbf4Life cbf4life@126.com 
     * I'm glad to share my knowledge with you all. 
     * 通用单例模式 
     */ 
    @SuppressWarnings("all") 
    public class SingletonPattern { 
      private static final SingletonPattern singletonPattern= new 
    SingletonPattern(); 
      
      //限制住不能直接产生一个实例 
      private SingletonPattern(){ 
     } 
      
      public synchronized static SingletonPattern getInstance(){  
       return singletonPattern; 
     } 
     

    接 new 一个对象传递给类的成员变量 singletonpattern,你要的时候 getInstance()直接返回给你,解决问题! 

    如果一件事情你觉得难的完不成,你可以把它分为若干步,并不断寻找合适的方法。最后你发现你会是个超人。不要给自己找麻烦,但遇到麻烦绝不怕,更不要退缩。 电工查找电路不通点的最快方法是:分段诊断排除,快速定位。你有什么启示吗? 求知若饥,虚心若愚。 当你对一个事情掌控不足的时候,你需要做的就是“梳理”,并制定相应的规章制度,并使资源各司其职。
  • 相关阅读:
    [LeetCode 1029] Two City Scheduling
    POJ 2342 Anniversary party (树形DP入门)
    Nowcoder 106 C.Professional Manager(统计并查集的个数)
    2018 GDCPC 省赛总结
    CF 977 F. Consecutive Subsequence
    Uva 12325 Zombie's Treasure Chest (贪心,分类讨论)
    Poj 2337 Catenyms(有向图DFS求欧拉通路)
    POJ 1236 Network of Schools (强连通分量缩点求度数)
    POJ 1144 Network (求割点)
    POJ 3310 Caterpillar(图的度的判定)
  • 原文地址:https://www.cnblogs.com/wvqusrtg/p/4812968.html
Copyright © 2011-2022 走看看