美文网首页
SingletonPattern单例模式

SingletonPattern单例模式

作者: jeff_chang_liu | 来源:发表于2020-08-04 21:17 被阅读0次

    单例模式

    1.定义

    确保某一个类只有一个实例,而且自行实例化并向整个系统提供这个实例

    饿汉式单例模式

    public class Singleton {
        private static final Singleton singleton = new Singleton();
    
        // 构造器私有化,限制产生多个对象
        private Singleton() {}
    
        // 对外提供静态方法获取实例对象
        public static Singleton getInstence() {
            return singleton;
        }
    }
    

    2.应用

    2.1优点

    • 由于单例模式在内存中只有一个实例,减小了内存开支。特别在一个对象需要频繁的创建销毁时,创建销毁时性能无法优化,此时的优势非常明显
    • 由于单例模式只生成一个实例,减少了系统的性能开销。当一个对象需要产生较多的资源时,如读取配置,产生其它以来对象,可以通过在应用启动时直接产生一个单例对象,然后永久驻留内存的方式解决(JavaEE中采用单例模式时需要注意JVM的垃圾回收机制)
    • 单例模式可以避免对同一资源的多重占用,例如写文件操作

    2.2缺点

    • 单例模式一般没有接口,扩展性差
    • 单例模式不利于测试。在并行开发环境中,若单例模式没有完成,不能进行测试

    2.3使用场景

    • 生成唯一序列号的环境
    • 在整个项目中需要一个共享访问点或共享数据。如一个Web页面上的计数器,使用单例模式保持计数器的值,并确保是线程安全的
    • 创建一个对象时需要消耗的资源过多,如访问IO和数据库等资源
    • 需要定义大量的静态常量和静态方法(如工具类)的环境

    2.4注意事项

    在该并发情况下,需要注意单例模式的线程同步问题。单例模式有几种不同的实现方式,饿汉式单例模式不会产生多实例的情况,以下方式则需要考虑线程同步问题

    懒汉式单例模式

    public class Singleton {
        private static final Singleton singleton = null;
    
        // 构造器私有化,限制产生多个对象
        private Singleton() {}
    
        // 对外提供静态方法获取实例对象
        public static Singleton getInstence() {
            if (singleton == null) {
              singleton = new Singleton();
            }
          
            return singleton;
        }
    }
    

    懒汉式单例模式在低并发情况下尚不会出现问题,若系统压力增大,并发量增加时可能在内存中存在多个实例。如一个线程A执行到singleton = new Singleton();但还没有获得到对象,此时对象初始化未完成,第二个线程B执行到if (singleton == null) {那么线程B判断条件也为true,于是继续执行下去,则A和B各获得一个对象。

    解决单例模式线程不安全的方法,可以在getInstence方法前或方法内加synchronized关键字来实现,建议采用饿汉式单例模式。

    3.扩展

    有上限的多例模式:产生固定数量对象的模式

    public class Singleton {
            // 定义最多能产生的实例数量
        private static int maxNumOfInstance = 2;
    
        // 定义一个列表容纳所有实例
        private static List<Singleton> singletonList = new ArrayList<>();
    
        // 定义当前对象实例的序号
        private static int countNumOfInstance = 0;
    
        // 产生所有的对象
        static {
            for (int i = 0; i < maxNumOfInstance; i++) {
                singletonList.add(new Singleton())
            }
        }
    
        private Singleton() {}
    
        public static Singleton getInstence() {
            Random random = new Random();
            countNumOfInstance = random.nextInt(maxNumOfInstance);
    
            return singletonList.get(countNumOfInstance);
        }
    }
    

    考虑到线程安全问题可以使用Vector来代替。采用有上限的多例模式,可以在设计时决定内存中有多少个实例,方便系统扩展,修正单例可能存在的性能问题,提高系统的响应速度。如读取文件,可以在系统启动时完成初始化工作,在内存中启动固定数量的Reader实例。

    相关文章

      网友评论

          本文标题:SingletonPattern单例模式

          本文链接:https://www.haomeiwen.com/subject/lskirktx.html