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

    1.单例模式的优点:避免多次使用对象的频繁创建,撤销。
    2.几种单例模式
    <1>懒汉式,比较懒,最后new实例

    package com.java.单例模式;
    /** 
     * @author wangpei 
     * @version 创建时间:2017年8月18日 下午11:22:41 
     * 懒汉式
     */
    public class Main {
        private static Main main;
        private Main(){}
        public synchronized static Main getInstance(){
            if(main==null)
                main=new Main();
            return main;
        }
    
    }
    

    2.饿汉式,因为比较饿了,所以得快点创建。

    package com.java.单例模式;
    /** 
     * @author wangpei 
     * @version 创建时间:2017年8月18日 下午11:25:14 
     * 饿汉式
     */
    public class Main2 {
        private static final Main2 main=new Main2();
        private Main2(){}
        public synchronized static Main2 getInstance(){
            return main;
    
        }
    
    }
    

    3.双重检验锁

    package com.java.单例模式;
    /** 
     * @author wangpei 
     * @version 创建时间:2017年8月18日 下午11:27:05 
     * 双重检验锁
     */
    public class Main3 {
        private static volatile Main3 main;
        private Main3(){}
        public static Main3 getInstance(){
            if(main==null){
                synchronized(Main3.class){
                    if(main==null)
                        main=new Main3();
                }
    
            }
            return main;
        }
    
    }
    

    第一层检验:当main不为null时,直接返回结果
    第二层检验:当线程A,线程B均判断main==null,线程A获得类锁,进入,创建对象,释放锁,线程B得到锁,若没有判断main==null,则其会再new一个。
    加入volatile修饰的原因:
    达到多线程访问时的可见性。
    线程A正在执行new Main3(),而线程B判断main!=null,可能得到一个初始化未完成的main对象。添加volatile,可以保证先行发生规则,write优先于读,所以,A写完,B才读。
    双重校验锁在安全方面还是不够,例如可以通过java反射,序列化,反序列化实现创建实例。

    4.枚举类型实现
    enum结构不能够作为子类继承其他类,但是可以用来实现接口。此外,enum类也不能够被继承,在反编译中,我们会发现该类是final的。其次,enum有且仅有private的构造器,防止外部的额外构造,

    package com.java.单例模式;
    
    /**
     * @author wangpei
     * @version 创建时间:2017年8月18日 下午11:45:44 枚举类型实现单例模式
     */
    public enum Main4 {
        INSTANCE;
        public void doSomething() {
            System.out.println("hello");
    
        }
    
    }
    

    分析:对于序列化和反序列化,因为每一个枚举类型和枚举变量在JVM中都是唯一的,即Java在序列化和反序列化枚举时做了特殊的规定,枚举的writeObject、readObject、readObjectNoData、writeReplace和readResolve等方法是被编译器禁用的,因此也不存在实现序列化接口后调用readObject会破坏单例的问题。

    对于线程安全方面,类似于普通的饿汉模式,通过在第一次调用时的静态初始化创建的对象是线程安全的。

  • 相关阅读:
    HTML5新特性,新的 Input 类型
    HTML5新特性,拖放(Drag 和 Drop)
    剑指 Offer 32
    剑指 Offer 28. 对称的二叉树
    993. 二叉树的堂兄弟节点
    897. 递增顺序查找树
    872. 叶子相似的树
    637. 二叉树的层平均值
    617. 合并二叉树
    559. N叉树的最大深度
  • 原文地址:https://www.cnblogs.com/wangxiaopei/p/8551262.html
Copyright © 2011-2022 走看看