首页 > 其他 > 详细

创建型 | 单例模式

时间:2021-04-04 09:09:01      阅读:43      评论:0      收藏:0      [点我收藏+]
创建型 | 单例模式介绍
       采取一定的方法保证在整个软件系统中,对某个类只能存在一个对象市里,并且该类只提供一个取得其对象实例的方法。
 
创建型 | 单例模式八种方式
  1. 饿汉式(静态常量)
    package singleton;
    
    /*
     * 创建型|单例模式|饿汉式(静态常量)
     * 优缺点说明:
     * 1>优点:写法简单,类装载的时候完成实例化。避免了线程同步问题。
     * 2>缺点:在类装载的时候就完成实例化,没有达到Lazy loading的效果。
     *        如果从始至终没用过这个实例,则会造成内存浪费。
     * 3>基于classloder机制避免了多线程的同步问题。不过instance在类
     *   装载时就实例化,在单利模式中大多是都基于getinstance方法,但是导致
     *   类装载的原因有很多种,因此不能确定有其它的方式(或者其它的静态方法)
     *   导致类装载,这时候初始化instance就没有达到lazy loading的效果。
     * 4>结论:这种单例模式可用,可能造成内存浪费。
     * */
    public class HungryMS1 {
        public static void main(String[] args) {
            Singleton singleton1 = Singleton.getInstance();
            Singleton singleton2 = Singleton.getInstance();
            System.out.println(singleton1 == singleton2);// true
            System.out.println("singleton1 hashCode:" + singleton1.hashCode());
            System.out.println("singleton2 hashCode:" + singleton2.hashCode());
        }
    }
    
    class Singleton {
        //1 构造器私有化,外部能new
        private Singleton() {
    
        }
    
        //2 本类内部创建对象实例
        private final static Singleton instance = new Singleton();
    
        //3 对外提供一个共有静态方法,返回实例对象
        public static Singleton getInstance() {
            return instance;
        }
    }

     

  1. 饿汉式(静态代码块)
    package singleton;

    /*
    * 创建型|单例模式|饿汉式(静态代码块)
    * 优缺点说明:
    * 1>优点:写法简单,类装载的时候完成实例化。避免了线程同步问题。
    * 2>缺点:在类装载的时候就完成实例化,没有达到Lazy loading的效果。
    * 如果从始至终没用过这个实例,则会造成内存浪费。
    * 3>这种方式和静态变量的方式类似,只不过将类实例化的过程放在了静态代码块中,
    * 也是在类装载的时候,就执行静态代码块中的代码,初始化类的实例。优缺点一致。
    * 4>结论:这种单例模式可用,可能造成内存浪费。
    * */
    public class HungryMS2 {
    public static void main(String[] args) {
    Singleton2 singleton1 = Singleton2.getInstance();
    Singleton2 singleton2 = Singleton2.getInstance();
    System.out.println(singleton1 == singleton2);// true
    System.out.println("singleton1 hashCode:" + singleton1.hashCode());
    System.out.println("singleton2 hashCode:" + singleton2.hashCode());
    }
    }

    class Singleton2 {
    //1 构造器私有化,外部能new
    private Singleton2() {

    }

    //2 本类内部创建对象实例
    private static Singleton2 instance;
    // 在静态代码块中,创建单利对象
    static {
    instance=new Singleton2();
    }

    //3 对外提供一个共有静态方法,返回实例对象
    public static Singleton2 getInstance() {
    return instance;
    }
    }

     

  2. 懒汉式(线程不安全)
    package singleton;

    /*
    * 创建型|单例模式|懒汉式(线程不安全)
    * 优缺点说明:
    * 1>优点:写起到了Lazy Loading的效果,但是只能在单线程下使用
    * 2>缺点:如果在多线程下,一个线程进入if(singleton==null)判断语句块,还
    * 未来得及往下执行,另一个线程也通过了这个判断语句,这时候就会产生多
    * 个实例。所以在多线程环境下不可使用这种方式
    * 3>结论:在实际开发中,不要使用这种方式
    * */
    public class SluggardS1 {
    public static void main(String[] args) {
    Singleton3 singleton1 = Singleton3.getInstance();
    Singleton3 singleton2 = Singleton3.getInstance();
    System.out.println(singleton1 == singleton2);// true
    System.out.println("singleton1 hashCode:" + singleton1.hashCode());
    System.out.println("singleton2 hashCode:" + singleton2.hashCode());
    }
    }

    class Singleton3 {

    private static Singleton3 instance;

    private Singleton3() {
    }

    //提供一个静态的共有方法,当使用到该方法时,才会去创建instance
    //懒汉式
    public static Singleton3 getInstance() {
    if(instance==null){
    instance=new Singleton3();
    }
    return instance;
    }
    }

     

  3. 懒汉式(线程安全,同步方法)
    package singleton;
    
    /*
     * 创建型|单例模式|懒汉式(线程安全,同步方法)
     * 优缺点说明:
     * 1>优点:解决类线程不安全问题
     * 2>缺点:效率太低,每个线程在执行getInstance()方法都要进行同步。方法进行同步效率低
     * 3>结论:在实际开发中,不推荐使用这种方式
     * */
    public class SluggardS2 {
        public static void main(String[] args) {
            Singleton4 singleton1 = Singleton4.getInstance();
            Singleton4 singleton2 = Singleton4.getInstance();
            System.out.println(singleton1 == singleton2);// true
            System.out.println("singleton1 hashCode:" + singleton1.hashCode());
            System.out.println("singleton2 hashCode:" + singleton2.hashCode());
        }
    }
    
    class Singleton4 {
    
        private static Singleton4 instance;
    
        private Singleton4() {
        }
    
        //提供一个静态的共有方法,加入同步处理的代码,解决线程安全问题
        //懒汉式
        public static synchronized Singleton4 getInstance() {
            if(instance==null){
                instance=new Singleton4();
            }
            return instance;
        }
    }

     

  4. 懒汉式(线程安全,同步代码块)
    package singleton;
    
    /*
     * 创建型|单例模式|懒汉式(线程安全,同步代码块)
     * 优缺点说明:
     * 1>本意是对同步方法进行改进,但是并不能起到线程同步的作用
     * 3>结论:在实际开发中,不能使用这种方式
     * */
    public class SluggardS3 {
        public static void main(String[] args) {
            Singleton5 singleton1 = Singleton5.getInstance();
            Singleton5 singleton2 = Singleton5.getInstance();
            System.out.println(singleton1 == singleton2);// true
            System.out.println("singleton1 hashCode:" + singleton1.hashCode());
            System.out.println("singleton2 hashCode:" + singleton2.hashCode());
        }
    }
    
    class Singleton5 {
    
        private static Singleton5 instance;
    
        private Singleton5() {
        }
    
        //提供一个静态的共有方法,同步处理代码放入if下
        //懒汉式
        public static Singleton5 getInstance() {
            if(instance==null){
                synchronized(Singleton5.class){
                    instance=new Singleton5();
                }
            }
            return instance;
        }
    }

     

  5. 双重检查
    package singleton;
    
    /*创建型|单例模式|双重检查
     * 1>双重检查概念是多线程开发中常使用到的,如代码中所示,进行了两次检查,可以保证线程安全
     * 2>线程安全;延迟加载;效率较高(延时加载的实现)
     * 3>结论:在实际开发中,推荐使用这种单例设计模式
     * */
    public class DuplicationCheck {
        public static void main(String[] args) {
            DCSingleton singleton1 = DCSingleton.getInstance();
            DCSingleton singleton2 = DCSingleton.getInstance();
            System.out.println(singleton1 == singleton2);// true
            System.out.println("singleton1 hashCode:" + singleton1.hashCode());
            System.out.println("singleton2 hashCode:" + singleton2.hashCode());
        }
    }
    
    class DCSingleton {
        private static volatile DCSingleton instance;
    
        private DCSingleton() {
        }
    
        //提供一个静态的共有方法,加入双重检查代码,解决线程安全问题,同事解决懒加载问题
        //同时保证了效率,推荐使用
        public static DCSingleton getInstance() {
            if (instance == null) {
                synchronized (DCSingleton.class) {
                    if (instance == null) {
                        instance = new DCSingleton();
                    }
                }
            }
            return instance;
        }
    }

     

  6. 静态内部类
    package singleton;
    
    /*创建型|单例模式|静态内部类
     * 1>采用类装载机制保证初始化实例只有一个线程
     * 2>静态内部类方式在单例类呗装载时不会立即实例化,而是在需要实例化时,调用
     *   getInstance方法,才会装载SingletonInstance类,从而完成Singleton的实例化
     * 3>类的静态属性只会在第一次加载类的时候初始化,所以在这里,JVM帮助我们保证了线程安全,
     *   在类进行初始化时,别的线程是无法进入的。
     * 4>优点:避免了线程不安全,利用静态内部类特点实现延迟加载,效率高
     * 5>结论:推荐使用
     * */
    public class StaticInner {
        public static void main(String[] args) {
            SISingleton singleton1 = SISingleton.getInstance();
            SISingleton singleton2 = SISingleton.getInstance();
            System.out.println(singleton1 == singleton2);// true
            System.out.println("singleton1 hashCode:" + singleton1.hashCode());
            System.out.println("singleton2 hashCode:" + singleton2.hashCode());
        }
    }
    
    class SISingleton {
        private static volatile SISingleton instance;
    
        private SISingleton() {
        }
    
        //写一个静态内部类,该类中有一个静态属性Singleton
        private static class SISingletonInstance {
            //JVM底层提供的类的装载机制保证线程安全
            private static final SISingleton INSTANCE = new SISingleton();
        }
    
        //提供一个静态的共有方法,直接返回SingletonInstance.INSTANCE
        public static synchronized SISingleton getInstance() {
            return SISingletonInstance.INSTANCE;
        }
    }

     

  7. 枚举
    package singleton;
    
    /*创建型|单例模式|枚举
     * 1>借助JDK1.5中添加的枚举来实现单例模式,不仅能变多线程同步问题,而且还能方式反序列化重新创建新的对象
     * 2>这种方式是Effective Java作者Josh Bloch提倡的方式
     * 3>结论:推荐使用
     * */
    public class EnumStyle {
        public static void main(String[] args) {
            ESingleton singleton1=ESingleton.INSTANCE;
            ESingleton singleton2=ESingleton.INSTANCE;
            System.out.println(singleton1 == singleton2);// true
            System.out.println("singleton1 hashCode:" + singleton1.hashCode());
            System.out.println("singleton2 hashCode:" + singleton2.hashCode());
        }
    }
    
    //使用枚举,可以实现单利
    enum ESingleton{
        INSTANCE;
        public void method(){
            System.out.println("ok~");
        }
    }

     

创建型 | 单例模式

原文:https://www.cnblogs.com/Arrogance/p/14615451.html

(0)
(0)
   
举报
评论 一句话评论(0
关于我们 - 联系我们 - 留言反馈 - 联系我们:wmxa8@hotmail.com
© 2014 bubuko.com 版权所有
打开技术之扣,分享程序人生!