zoukankan      html  css  js  c++  java
  • 设计模式第五篇-单例模式

    一、引言

    单例模式应该是设计模式中比较简单的一个,因为这个模式只有一个类,但不要小看这个设计模式,这个模式可是面试的时候很常见的一个。

    单例模式有什么的用处:有一些对象我们只需要一个的时候,比如线程池,缓存,注册表等。

    也就是说这个模式的作用是:保证只有一个实例对象

    二、单例模式

    先看定义:确保一个类只有一个实例,并提供一个全局访问点。

    开始思考,我们如何确保只有一个实例?

    首先要知道我们是如何创建的对象的,这个很容易回答:用new关键字,只要是公开类,我们在外部就可以无限的实例化,也是就说第一步就是要将类私有化。

    如何私有化:使用私有构造构造器,一旦使用私有构造器,那么外部便不能实例化。

    可一旦使用私有构造器,那么不是只有内部才能调用这个构造器么?既然外部不能实例化,那么如何去调用这个私有构造器呢?

    这个时候静态方法就起作用了,我们定义一个静态方法,通过静态方法去调用私有构造器,问题就解决了。

    通过上面的思考,代码就已经出来了:

    //单例模式实现-懒汉式
    public class Singleton {
    
        //利用静态变量记录类的唯一实例
        private static Singleton  uniqueInstance;
        //把构造器设置为私有,只有内部才可以调用构造器
        private Singleton(){}
        //用静态方法实例化对象
        public static Singleton getInstance(){
            //如果为空则说明还没有创建实例,这个时候我们可以创建,这个就是延时实例化,也就是传说中的懒汉式
            if(uniqueInstance==null){
                uniqueInstance = new Singleton();
            }
            return uniqueInstance;
        }
        public void showMsg(){
            System.out.println("其他方法,显示数据");
        }
    }

    这种实现方法叫做懒汉式,但这种懒汉模式存在一个问题:线程不安全,在多线程情况下,完全有可能生成多个实例,这个时候可以用synchronized关键字来处理。

     public static synchronized Singleton getInstance(){
     ...
    }

    当然,加锁会降低一些性能。

    其实还有一种方法,那就是饿汉式

    //单例模式-饿汉式
    public class Singleton1 {
        //初始化器重直接创建,可以保证线程安全
        private static Singleton1 uniqueInstance=new Singleton1();
        //静态方法
        private Singleton1(){}
        //直接返回
        public static Singleton1 getInstance(){
            return uniqueInstance;
        }
    }

    这样的方式容易产生垃圾对象,浪费一些内存,但是没有加锁,效率提高很多(一般情况下推荐使用这种方式)。

    另外还有一种凡是:双重检查加锁

    //双重加锁方式
    public class Singleton2 {
        //利用volatile 关键字保证多个线程正确使用uniqueInstance
        private volatile  static Singleton2 uniqueInstance;
        private Singleton2(){}
    
        public static Singleton2 getInstance(){
            //检查实例,不存在则进入同步代码块
            if(uniqueInstance==null){
                //同步代码块
                synchronized (Singleton2.class){
                    //进入代码块后,再判断一次
                    if(uniqueInstance==null){
                        uniqueInstance=new Singleton2();
                    }
                }
            }
            return uniqueInstance;
        }
    }

    这种方式可以大大提高性能,就是实现有些复杂(且不支持1.4之前的版本)

    三、总结

    单例模式是一个相对简单的模式,主要的核心在私有化构造器,及暴露一个静态方法创建实例,再考虑多线程相关情况。

  • 相关阅读:
    后勤数据抽取流程图 Logistic Data Extraction
    WINDOWS两条线路上网的解决办法
    Zabbix Agent for Linux部署
    Java项目的自动更新并构建脚本
    使用Goole搜索引擎
    golang程序性能优化方法----不断更新
    golang性能分析策略
    问题分析:引入新elastic api导致的TIME_WAIT堆积
    数据权限限定办法
    MariaDB集群搭建
  • 原文地址:https://www.cnblogs.com/yuanqinnan/p/10167684.html
Copyright © 2011-2022 走看看