zoukankan      html  css  js  c++  java
  • java单例设计模式

    单例设计模式是在软件系统中采用一定的方法,保证某个类只能存在一个实例对象,并且该类只能有一个静态方法来获取该对象。

    注意下面各类实现方式中的测试代码都一样:需要注意导入的包路径即可。

    package com.yefengyu;
    
    import com.yefengyu.type2.Singleton;
    
    
    public class Client
    {
        public static void main(String[] args)
        {
            Singleton singleton1 = Singleton.getInstance();
            Singleton singleton2 = Singleton.getInstance();
            System.out.println(singleton1 == singleton2);
        }
    }

    1、实现方式一


    该方式是静态常量实现的饿汉式类加载的时候便创建了实例):

    package com.yefengyu.type1;
    
    public class Singleton
    {
        //类内部实例化
        private final static Singleton INSTANCE = new Singleton();
    
        //构造器私有化,防止new对象
        private Singleton()
        {
        }
    
        //对外提供公有方法调用
        public static Singleton getInstance()
        {
            return INSTANCE;
        }
    }

    1、类加载的时候实例化,防止多线程问题。

    2、没有使用懒加载,类加载就产生对象,如果始终未使用则造成内存浪费。但是该对象只有一个,浪费空间也不是很大,可以使用,编写的时候非常简单。

    2、实现方式二

    该方式是静态代码块实现的饿汉式

    package com.yefengyu.type2;
    
    public class Singleton
    {
        private final static Singleton INSTANCE;
    
        static
        {
            //使用静态代码块生成对象
            INSTANCE = new Singleton();
        }
    
        //构造器私有化,防止new对象
        private Singleton()
        {
        }
    
        //对外提供公有方法调用
        public static Singleton getInstance()
        {
            return INSTANCE;
        }
    }

    该方式和方式一的优缺点类似。

    3、实现方式三


    该方式是同步方法实现懒汉式只有第一次使用的时候才创建实例

    package com.yefengyu.type3;
    
    public class Singleton
    {
        private static Singleton instance;
    
        //构造器私有化,防止new对象
        private Singleton()
        {
        }
    
        //只有在第一次使用的时候构造实例对象,使用synchronized避免多线程问题
        public static synchronized Singleton getInstance()
        {
            if (instance == null)
            {
                instance = new Singleton();
            }
            return instance;
        }
    }

    1、解决了线程不安全问题

    2、效率低下,每次调用该方法都要涉及锁的操作。

    3、不推荐使用。

    问:java设计模式的单例模式,在懒汉式中一开始声明的类的实例化对象为什么只用private static声明,但没有加final关键字?而在饿汉式中声明实例是使用了private static final修饰?

    答:如果是final非static成员,必须在构造器、代码块、或者直接定义赋值;如果是final static成员变量,必须直接赋值或者在静态代码块中赋值。而在懒汉式中如果直接赋值就达不到延迟加载的效果。

    4、实现方式四


    该方式是同步代码块实现懒汉式。

    package com.yefengyu.type4;
    
    public class Singleton
    {
        private static Singleton instance;
    
        //构造器私有化,防止new对象
        private Singleton()
        {
        }
    
        //只有在第一次使用的时候构造实例对象,使用synchronized代码块和双重判断避免多线程问题,并且提供效率
        public static Singleton getInstance()
        {
            if (instance == null)
            {
                synchronized (Singleton.class)
                {
                    if (instance == null)
                    {
                        instance = new Singleton();
                    }
                }
            }
            return instance;
        }
    }

    1、解决了线程不安全问题

    2、效率高,只有前面的少数线程可能会获取锁,只要实例被创建,后面的线程一般只需第一个if判断就返回了对象。

    3、推荐使用。

    5、实现方式五


    该方式是静态内部类实现懒汉式。

    package com.yefengyu.type5;
    
    public class Singleton
    {
        private static Singleton instance;
    
        //构造器私有化,防止new对象
        private Singleton()
        {
        }
    
        //静态内部类,在外部类加载的时候不会加载静态内部类
        private static class SingletonInstance
        {
            private static final Singleton INSTANCE = new Singleton();
        }
    
        public static Singleton getInstance()
        {
            //只有在使用到静态内部类的时候才会加载,并且通过类加载机制保证在初始化的时候只有一个实例产生
            return SingletonInstance.INSTANCE;
        }
    }

    1、线程安全,使用类加载机制保证初始化时只有一个线程。

    2、外部类装载的时候静态内部类不会装载,只有使用的时候才会装载,因此达成了懒汉式的效果。


    单例设计模式的使用场景?

    一个对象即可完成所有的工作,无需大量创建对象消耗资源。比如一个长连接,建立起来就可以不断发送数据,此时如果每来一个请求就建立一个连接,那么资源会消耗殆尽。

    多线程测试:针对懒汉式

    测试代码:

    for (int i = 0; i < 1000; i++)
    {
        new Thread(() -> {
            Singleton.getInstance();
        }).start();
    }

    在new实例的时候加上打印,如:

    public static synchronized Singleton getInstance()
    {
        if (instance == null)
        {
            System.out.println("创建实例");
            instance = new Singleton();
        }
        return instance;
    }
    这个时候可以去掉synchronized关键字,或者加上,查看打印效果,是打印一句还是多句。
  • 相关阅读:
    软件设计文档
    java基础路线与详细知识点
    hdu 2203 亲和串 kmp
    UVALive 6915 J
    UVALive 6911 F
    UVALive 6906 A
    hdu 3746 Cyclic Nacklace KMP
    hdu 1686 Oulipo kmp算法
    hdu1711 Number Sequence kmp应用
    hdu4749 kmp应用
  • 原文地址:https://www.cnblogs.com/ye-feng-yu/p/11183075.html
Copyright © 2011-2022 走看看