• 设计模式之单例设计模式


    1.饿汉式单例模式

    /**
     * 饿汉式单例模式
     * 线程安全的,但是会造成内存浪费,尤其是在没有真正使用到的情况下,性能上也是浪费。
     */
    public class SingletonDemo {
    
        private SingletonDemo () {}
    
        private static SingletonDemo singletonDemo = new SingletonDemo();
    
        public static SingletonDemo getInstance() {
            return singletonDemo;
        }
    
    }
    
    /**
     * 饿汉式单例模式
     * 利用静态代码块来解决
     */
    public class SingletonDemo5 {
    
        private SingletonDemo5() {}
        private static SingletonDemo5 singletonDemo = null;
    
        static {
            singletonDemo = new SingletonDemo5();
        }
    
        public static SingletonDemo5 getInstance() {
            return singletonDemo;
        }
    
        public static void main(String[] args) {
            System.out.println(SingletonDemo5.getInstance());
            System.out.println(SingletonDemo5.getInstance());
        }
    
    }
    
    

    2.懒汉式单例

    /**
     * 懒汉式单例模式
     * 线程不安全的,比起饿汉式性能资源上更有优势。
     */
    public class SingletonDemo1 {
    
        private SingletonDemo1() {}
    
        private static SingletonDemo1 singletonDemo = null;
    
        public static SingletonDemo1 getInstance() {
            /**
             * 线程不安全出现在下面的if代码块
             * Thread_A 和 Thread_B同时到达if的时候,就会出现两个对象实例。
             */
            if(null == singletonDemo){
                singletonDemo = new SingletonDemo1();
            }
            return singletonDemo;
        }
    }
    
    

    下面就进行修改,让它成为线程安全的!
    变型一:

    /**
     * 懒汉式单例模式
     * 线程安全的,比起饿汉式性能资源上更有优势。
     */
    public class SingletonDemo2 {
    
        private SingletonDemo2() {}
    
        private static SingletonDemo2 singletonDemo = null;
    
        /**
         * synchronized 只会让一个线程进入创建对象实例。但是
         *  会造成性能问题。
         * @return
         */
        public synchronized static SingletonDemo2 getInstance() {
    
            if(null == singletonDemo){
                singletonDemo = new SingletonDemo2();
            }
            return singletonDemo;
        }
    }
    

    变型二:

    /**
     * 懒汉式单例模式
     * 线程不安全的,比起饿汉式性能资源上更有优势。
     */
    public class SingletonDemo3 {
    
        private SingletonDemo3() {}
    
        private static SingletonDemo3 singletonDemo = null;
    
        /**
         * synchronized 下沉到方法内部,这种形式也可以叫做:
         * 双重检测同步机制
         * 这样同样会有问题:造成的原因是指令重排序
         *
         * 创建对象简单过程:
         *  1.分配对象内存空间
         *  2.引用指向刚才分配的内存空间
         *  3.初始化对象
         *
         *  指令重排序会让:2、3进行颠倒
         *
         *
         * @return
         */
        public synchronized static SingletonDemo3 getInstance() {
    
            if(null == singletonDemo){   // 线程A  如果是132的过程B->3,A在此处就会直接返回未完成初始化的对象实例
                synchronized (SingletonDemo.class) {
                    if (null == singletonDemo) {
                        singletonDemo = new SingletonDemo3(); // 线程B - 1【3】2执行到第三步
                    }
                }
            }
            return singletonDemo;
        }
    }
    
    

    针对变型二里面出现的问题,这个时候就要上volatile 这个杀器了,他可以让程序屏蔽指令重排序:

    /**
     * @author Kevin 
     * 
     * 单例设计模式
     *
     */
    public class SingletonDemo {
    	private SingletonDemo(){
    		//不可实例化
    	}
    	/**
    	 * volatile保持可见性
    	 */
    	private volatile static SingletonDemo singleton;
    	
    	/**
    	 * @return SingletonDemo
    	 * 
    	 * 此方法再指令重排序时候,不能保证安全单例,所以使用volatile。
    	 * 
    	 */
    	public static SingletonDemo getInstance(){
    		if(singleton == null){
    			synchronized (SingletonDemo.class) {
    				if(singleton == null){
    					singleton = new SingletonDemo();
    				}
    			}
    		}
    		return singleton;
    	}
    
    }
    

    3.利用枚举类的单例写法(推荐)

    public class SingletonEnumDemo {
        private SingletonEnumDemo() {}
    
        public synchronized static SingletonEnumDemo getInstance() {
            return Singleton.INSTANCE.getInstance();
        }
    
        private enum Singleton {
            INSTANCE;
            private SingletonEnumDemo singletonDemo = null;
    
            // JVM保证该方法只会被调用一次,绝对安全
            Singleton () {
                singletonDemo = new SingletonEnumDemo();
            }
    
            public SingletonEnumDemo getInstance () {
                return singletonDemo;
            }
        }
    }
    
  • 相关阅读:
    BCTF赛后
    有道前端面试总结
    来更新一篇blog吧
    好久没更新了,开学新气象
    leetcode--N-Queens II
    leetcode--N-Queens
    leetcode--Scramble String
    leetcode--Maximal Rectangle
    leetcode--Distinct Subsequences
    leetcode--Sudoku Solver
  • 原文地址:https://www.cnblogs.com/Kevin-1992/p/12608430.html
Copyright © 2020-2023  润新知