• 单例模式的几种实现方式


    实现方式大致分为两种

    • 懒汉模式
    • 饿汉模式

    懒汉模式:在第一次使用该对象时,才会初始化实例,以免了资源的浪费,同时,需要考虑的是线程安全问题。

    饿汉模式:在类初始化时就需要创建一个实例对象出来,当时并不一定会使用该对象,可能会造成资源的浪费,好处是不用考虑安全问题。

    下面看下几种常见的实现方式:

    首先看懒汉模式:

    1、线程非安全版本,可在单线程下使用

    /**
     * 懒汉式单例,线程不安全,只有在第一次调用时才会初始化一次,
     * 但是线程不安全,如果在初始化时需要消耗大量的资源,则会造成资源的浪费,同时,在并发场景中,可能造成变量的变化等问题。
     * @author woniu
     *
     */
    public class Singleton1
    {
        private Singleton1(){}
        private static Singleton1 instance = null;
        
        public static Singleton1 getInstance()
        {
            if (instance == null)
            {
                instance = new Singleton1();
            }
            return instance;
        }
    }

    关于懒汉模式的几种线程安全版本,详细的说明已在类中说明,不在单独说明。

    1、在getInstance方法上加同步

    /**
     * 懒汉式单例,线程安全,与第一种无异,仅是通过synchronized,将getInstance实现为了同步方法,
     * 但是,这就造成了getInstance方法,仅能同时只有一个线程调用,但是,在除去第一次初始化外,我们大多数情况下,并不需要防止同步问题。
     * @author woniu
     */
    public class Singleton2
    {
        private Singleton2(){}
        private static Singleton2 instance = null;
        
        public static synchronized Singleton2 getInstance()
        {
            if (instance == null)
            {
                instance = new Singleton2();
            }
            return instance;
        }
    }

    2、双重检查锁定

    /**
     * 此方法被称为双重校验锁,在示例2的基础之上将同步方法,修改为了同步代码块,仅是在需要初始化时,才需要加锁,这样就避免了在大多数情况下不需要同步的问题。
     * 关于之所以在同步方法块中再次进行判断的原因:根据并发编程实战中的提到的“先检查后执行”的操作是非原子性的,简而言之就是,避免用一个过期的变量作为当前的判断标准。
     * 连接:http://www.cnblogs.com/woniu4/p/8284244.html
     * @author woniu
     *
     */
    public class Singleton3
    {
        private Singleton3(){}
        private volatile static Singleton3 instance = null;
        
        public static Singleton3 getInstance()
        {
            if (instance == null)
            {
                synchronized(Singleton3.class)
                {
                    if (instance == null)
                    {
                        instance = new Singleton3();
                    }
                }
            }
            return instance;
        }
    }

    3、静态内部类

    /**
     * 单例同样可以通过内部类的方式实现,这样就避免了同步带来的性能开销(虽说现在synchronize方法已经做了很大的优化,对性能的影响已经降低了很多,但终究还是有一定影响的。)
     * 虽说这种方式比较好,但是在我们当前项目中,似乎大家都比较懒,直接用了方法2中的模式,毕竟,当前的工程性项目,并没有对项目性能有极高的要求。
     * @author woniu
     *
     */
    public class Singleton4
    {
        private Singleton4(){};
        
        private static class LasyHolder
        {
            private static final Singleton4 INSTANCE = new Singleton4();
        }
        
        public static Singleton4 getInstance()
        {
            return LasyHolder.INSTANCE;
        }
    }

    饿汉模式:

    /**
     * 饿汉模式,通过在类初始化时,已经实例化,这样本身就是线程安全的。
     * @author woniu
     *
     */
    public class Singleton5
    {
        private Singleton5(){}
        private static final Singleton5 INSTANCE = new Singleton5();
        
        public static Singleton5 getInstance()
        {
            return INSTANCE;
        }
    }

    最后有一种通过枚举实现的方式,算是一种比较新的方式吧。当前不清楚具体归属类型,暂且单列出来。

    /**
     * 枚举模式,没有使用过,仅是博客或者书见过这种方式,不仅能避免线程同步问题,而且还能防止反序列化重新创建新的对象,日后工作中,有类似需要单例场景中,可以考虑使用一下,写法还是十分简单的。
     * @author woniu
     *
     */
    public enum Singleton6
    {
        INSTANCE;
        
        public String testMethod()
        {
            return "test enum instance";
        }
        public static void main(String[] args)
        {
            String str = INSTANCE.testMethod();
            System.out.println(str);
        }
    }
  • 相关阅读:
    Ubuntu下基于Virtualenv构建Python开发环境
    Linux查看用户登录信息-last
    SpringCloud实践引入注册中心+配置中心
    git仓库构建小记
    windows下使用hbase/opencv/ffmpeg小记
    Java执行jar总结
    命名空间
    phpstudy ——composer使用
    template-web.js
    redis
  • 原文地址:https://www.cnblogs.com/woniu4/p/8287484.html
Copyright © 2020-2023  润新知