zoukankan      html  css  js  c++  java
  • 单例模式的实现

      单例模式就是是一个类仅可以创建一个对象,在java中实现主要有两种方式:饿汉式和懒汉式。

      先看两种方式共有的部分,因为是单例,所以构造方法必须是私有的private,而且必须提供一个对外界开放的获取对象的方法,该方法内部控制返回唯一的一个对象实例:

    public class Singleton {
    
        //构造方法私有,阻断外界直接创建对象的方法
        private Singleton() {}
        
        //提供一个获取唯一对象实例的方法
        public static Singleton getInstance(){
            //...
        }
        
    }

      以上是不管什么方式的实现,都得遵循的一些规定,下面就介绍懒汉式和饿汉式:

      饿汉式是单例类感觉自己很饥饿(将实例对象想象为吃的),不管有没有别的类跟我要实例类,我都要自己先生成一个,像下面的实现: 

    public class Singleton {
    
        //构造方法私有,阻断外界直接创建对象的方法
        private Singleton() {}
        
        //内部持有一个类初始化时唯一创建的一个类实例对象
        private static Singleton singleton = new Singleton();
        
        //提供一个获取唯一对象实例的方法
        public static Singleton getInstance(){
            return singleton;
        }
        
    }

      饿汉式的有点在于编码逻辑简单好理解,无线程安全问题;缺点嘛,自然就是当我仅仅是想用Singleton类其他方法,他还是创建了一个对我现在来说没用的实例对象,当系统中这种饿汉式的单例类多起来的时候,无疑是一种资源浪费,这个问题正好懒汉式可以解决。

      懒汉式,就是自己首先持有一个空的单例类的实例,但是不会类一加载就创建实例,只有当别人第一次要我的实例对象我才给他创建,懒嘛,要是没人要我就不创建了:

    public class Singleton {
    
        //构造方法私有,阻断外界直接创建对象的方法
        private Singleton() {}
        
        //内部持有一个单例类的引用
        private static Singleton singleton = null;
        
        //提供一个获取唯一对象实例的方法
        public static Singleton getInstance(){
            if(singleton==null){
                singleton = new Singleton();
            }
            return singleton;
        }
        
    }

      饿汉式的有点不用说了,就是解决了懒汉式的缺点;但是他的缺点就是多线程环境下,不尽人意啊,比如两个线程同时都是第一次去获取Singleton类的实例的时候,又同时执行到if(singleton==null)这一行,两个线程就会同时进入if语句执行体中去,可能先后执行了singleton = new Singleton();这就违反了单例模式的概念,所以还得想个办法解决这个问题。

      线程安全的饿汉式:(其实只要将if语句上加上线程锁,就可以避免两个线程一起跑到这个地方来了)

    public class Singleton {
    
        //构造方法私有,阻断外界直接创建对象的方法
        private Singleton() {}
        
        //内部持有一个单例类的引用
        private static Singleton singleton = null;
        
        //提供一个获取唯一对象实例的方法
        public static Singleton getInstance(){
            synchronized (Singleton.class) {
                if(singleton==null){
                    singleton = new Singleton();
                }
            }
            return singleton;
        }
        
    }

      踏哒~,解决了,但是!你发现了么?这样的话,每次别人想获取sinleton实例的时候都得等待别的线程释放锁,自己再加锁,自己再释放锁,而这些锁的操作又是那么消耗时间,能不能再优化一下。想一想,是不是第一次访问完了,只要sington对象实例,不为空,直接返回就是了,没有现成问题啊,应该这样:

    public class Singleton {
    
        //构造方法私有,阻断外界直接创建对象的方法
        private Singleton() {}
        
        //内部持有一个单例类的引用
        private static Singleton singleton = null;
        
        //提供一个获取唯一对象实例的方法
        public static Singleton getInstance(){
            if(singleton==null){
                synchronized (Singleton.class) {
                    if(singleton==null){
                        singleton = new Singleton();
                    }
                }
            }
            return singleton;
        }
        
    }

      完美!线程安全的懒汉式,既解决了资源浪费问题,又兼顾了线程安全问题。

      不过还有个更巧妙地方法,这个就涉及到内部类的只是,当一个类加载的时候,其内部类并不加载,而是只要第一次用到内部类的时候内部类才会加载,而且如果这个内部类是static内部类,也就是说加载了这个类一次,以后就直接获取他就可以了,详细参见另一篇博客:http://www.cnblogs.com/WreckBear/p/5812942.html

    public class Singleton {
    
        //构造方法私有,阻断外界直接创建对象的方法
        private Singleton() {}
        
        /*
         * 搭建一个内部静态类,外部类加载的时候,内部类并不会加载,
         * 只有当内部类被访问的时候才会被加载、初始化,加载之后就会一直保存在内存中
         */
        public static class Get{
            public static Singleton singleton = new Singleton();
        }
        
    }

      在Main中获取:

    public class Main {
    
        public static void main(String[] args) {
            Singleton singleton = Singleton.Get.singleton;
        }
    }

      这种方法显得更加优雅一点,至此,结束!

  • 相关阅读:
    js 百度地图和谷歌地图的选择
    angular4 自定义表单验证Validator
    推荐20个很有帮助的 Web 前端开发教程
    前端同学大福利,最全的面试题目整理
    前端开发:如何写一手漂亮的 Vue
    推荐20个很有帮助的 Web 前端开发教程
    面试分享:一年经验初探阿里巴巴前端社招
    想成为一个高效的Web开发者吗?来看看大牛分享的经验吧~ #精选JAVASCRIPT前端开发
    初学者Web介绍一些前端开发中的基本概念用到的技术
    Web设计新手应知道的10个锦囊妙计
  • 原文地址:https://www.cnblogs.com/WreckBear/p/5813003.html
Copyright © 2011-2022 走看看