• singleton单例模式小结


    1.饿汉模式

    public class SingletonEntity2 {
    
        // 在类加载的时候创建对象:饿汉模式
        public static SingletonEntity2 obj = new SingletonEntity2();
        
        // 构造方法私有化
        private SingletonEntity2(){}
        
        public static SingletonEntity2 getInstance(){
            return obj;
        }
        
    }

    2.懒汉模式

    public class SingletonEntity {
        
        // 静态变量存放在方法区中,类加载的时候赋值,而且只会赋值一次,懒汉模式
        public static SingletonEntity obj = null;
        
        // 构造方法私有化
        private SingletonEntity() {}
        
        // 对外提供获取实例的公开的静态的方法
        public static SingletonEntity getInstance() {
            if (obj == null) {
                obj = new SingletonEntity();
                System.out.println("新创建实例");
            }
            System.out.println("直接返回实例");
            return obj;
        }
        
    }

    3.测试类

    public static void main(String[] args) {
        
        SingletonEntity obj1 = SingletonEntity.getInstance();
        SingletonEntity obj2 = SingletonEntity.getInstance();
        System.out.println(obj1 == obj2); // true
    
    }

    ==========================================================================================================================================

    懒汉模式不安全性测试:

    1.起现成类:

    public class RunnableThreadTest implements Runnable {
        
        @Override
        public void run() {
            
            SingletonEntity obj = SingletonEntity.getInstance();
            System.out.println(Thread.currentThread().getName()+" "+obj);  
    
        }
    
    }

    2.测试类:

    public class SingletonTest {
    
        public static void main(String[] args) {
            
            Thread thread1 = new Thread(new RunnableThreadTest());
            Thread thread2 = new Thread(new RunnableThreadTest());
            thread1.start();
            thread2.start();
            
        }
    
    }

    3.运行结果:

    Thread-0 com.beijing.singleton.SingletonEntity@406866f9
    Thread-1 com.beijing.singleton.SingletonEntity@25eb939e

    ==========================================================================================================================================

    改善结果:推荐使用双检查锁机制

    public class SingletonEntity {
    
        // 静态变量存放在方法区中,类加载的时候赋值,而且只会赋值一次,懒汉模式
        public static volatile SingletonEntity obj = null;
    
        // 构造方法私有化
        private SingletonEntity() {
        }
    
        // 对外提供获取实例的公开的静态的方法
        public static SingletonEntity getInstance() {
            try {
                // 双检查所机制
                if (obj == null) {
                    synchronized (SingletonEntity.class) {
                        if (obj == null) {
                            Thread.sleep(1000);
                            obj = new SingletonEntity();
                        }
                    }
                }
            } catch (Exception e) {
                e.printStackTrace();
            }
            return obj;
        }
    
    }
    为什么要用volatile修饰instance?
    原因:在于instance = new SingletonEntity()的时候,在内存中实际上是分3步执行的:
    1)分配对象的内存空间:memory = allocate();
    2)初始化对象:ctorInstance(memory);
    3)指向分配的地址:instance =memory
    多线程在执行的时候,2 3可能发生重排序。即有可能线程A执行到第3步的时候,读取到instance不为null,就返回。实际上此时还未执行第二部即未初始化。
    加上volatile就可以避免2 3步重排序来保证线程安全。
  • 相关阅读:
    collections.ChainMap类合并字典或映射
    collections.namedtuple()命名序列元素
    过滤、修改和替换列表数据
    快速排序
    itertools.groupby()分组字典列表
    operator.attrgetter() 进行对象排序
    operator.itemgetter() 字典列表排序
    collections.Counter类统计列表元素出现次数
    递归
    正则表达式的一些题
  • 原文地址:https://www.cnblogs.com/zhangjianbing/p/8066526.html
Copyright © 2020-2023  润新知