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

    Java中单例模式定义:“一个类有且仅有一个实例,并且自行实例化向整个系统提供。”

    1.饿汉式

    package testSingletonUnderMultiThreads;
    
    /**
     * @author zhangdi
     * 饿汉式 : 存在效率和资源占用问题
     */
    public class Singleton_1_MyObject {
    // 饿汉式
    private static Singleton_1_MyObject myObject = new Singleton_1_MyObject();
    
    // private 只有内部才能调用构造器
    private Singleton_1_MyObject() {
        super();
    }
    
    //
    private static Singleton_1_MyObject getInstance() {
        return myObject;
    }
    
    }

    2.懒汉式:存在多线程下的线程安全问题

    package testSingletonUnderMultiThreads;
    
    /**
     * @author zhangdi
     * 懒汉式:存在多线程下的线程安全问题
     */
    public class Singleton_2_MyObject {
        // 定义一个静态变量来记录类的唯一实例,但不初始化
        private static Singleton_2_MyObject myObject;
    
        // 保证只有内部可以调用构造器
        private Singleton_2_MyObject() {
    
        }
    
        public static Singleton_2_MyObject getInstance() {
            if (null != myObject) {
    
            } else {
                myObject = new Singleton_2_MyObject();
            }
            return myObject;
    
        }
    }
    

    3.懒汉式加锁 :可解决多线程下的同步问题,但是存在严重效率问题

    
    /**
     * @author zhangdi
     *  synchronized 加锁 : 可解决多线程下的同步问题,但是存在严重效率问题
     */
    public class Singleton_3_MyObject {
        // 定义一个静态变量来记录类的唯一实例,但不初始化
        private static Singleton_3_MyObject myObject;
    
        // 保证只有内部可以调用构造器
        private Singleton_3_MyObject() {
    
        }
    
        //synchronized保证多线程下的懒汉式是线程安全的,但是问题在于,只有第一次执行时才需要同步,设置好MyObject后都不要同步这个方法了.
        synchronized public static Singleton_3_MyObject getInstance() {
            if (null != myObject) {
    
            } else {
                myObject = new Singleton_3_MyObject();
            }
            return myObject;
    
        }
    }
    

    4.DCL :双重加锁检查 :
    volatile是必须的.

    package testSingletonUnderMultiThreads;
    
    /**
     * @author zhangdi
     * 双重加锁检查 
     */
    public class Singleton_4_MyObject {
        //ps:volatile 保证线程间共享变量的可见性,但不能保证原子性
        //volatile确保myObject被初始化为singleton单例后,多个线程可以正确处理myObject
        private volatile static Singleton_4_MyObject myObject;
    
        private Singleton_4_MyObject() {
        }
    
        private static Singleton_4_MyObject getInstance() {
            //只有第一次才会彻底执行下面的代码
            if (myObject == null) {
                synchronized (Singleton_4_MyObject.class) {
                    //进入区块后,再检查一下,myObject仍为null,才创建实例
                    if(myObject == null){
                        myObject = new Singleton_4_MyObject();
                    }
                }
            }
            return myObject;
    
        }
    }
    

    5 . 使用静态内部类 :静态内部类虽然保证了单例在多线程并发下的线程安全性,但是在遇到序列化对象时,默认的方式运行得到的结果就是多例的。
    ps:静态内部类的加载不需要依附外部类,在使用时才加载,而不是在外部类加载时被加载

    package testSingletonUnderMultiThreads;
    
    /**
     * @author zhangdi
     * 使用静态内部类 
     * 静态内部类虽然保证了单例在多线程并发下的线程安全性,但是在遇到序列化对象时,默认的方式运行得到的结果就是多例的。
     */
    public class Singleton_5_MyObject {
        //静态内部类的加载不需要依附外部类,在使用时才加载,而不是在外部类加载时被加载
        private static class MyObjectHandler {
            private static Singleton_5_MyObject myObject = new Singleton_5_MyObject();
        }
        //私有构造器是必须的
        private Singleton_5_MyObject() {
        }
    
        public static Singleton_5_MyObject getInstance() {
            return MyObjectHandler.myObject;
    
        }
    }
    

    6.序列化与反序列化的单例模式实现

    package testSingletonUnderMultiThreads;
    
    import java.io.ObjectStreamException;
    import java.io.Serializable;
    
    /**
     * @author zhangdi
     * 序列化与反序列化的单例模式实现
     */
    public class Singleton_6_MyObject implements Serializable {
        private static final long serialVersionUID = 1L;
    
        private static class MyObjectHandler {
            private static Singleton_6_MyObject myObject = new Singleton_6_MyObject();
        }
    
        private Singleton_6_MyObject() {
        }
    
        public static Singleton_6_MyObject getInstance() {
            return MyObjectHandler.myObject;
    
        }
    
        // 该方法在反序列化时会被调用,该方法不是接口定义的方法,有点儿约定俗成的感觉
        protected Object readResolve() throws ObjectStreamException {
            System.out.println("调用了readResolve方法!");
            return MyObjectHandler.myObject;
        }
    
    }
    

    序列化与反序列化测试代码 :

    package testSingletonUnderMultiThreads;
    
    import java.io.File;
    import java.io.FileInputStream;
    import java.io.FileNotFoundException;
    import java.io.FileOutputStream;
    import java.io.IOException;
    import java.io.ObjectInputStream;
    import java.io.ObjectOutputStream;
    
    /**
     * @author zhangdi
     * 序列化与反序列化测试代码
     */
    public class SaveAndReadForSingleton {
    
        public static void main(String[] args) {
            Singleton_6_MyObject singleton = Singleton_6_MyObject.getInstance();
    
            File file = new File("MySingleton.txt");
    
            try {
                FileOutputStream fos = new FileOutputStream(file);
                ObjectOutputStream oos = new ObjectOutputStream(fos);
                oos.writeObject(singleton);
                fos.close();
                oos.close();
                System.out.println(singleton.hashCode());
            } catch (FileNotFoundException e) { 
                e.printStackTrace();
            } catch (IOException e) { 
                e.printStackTrace();
            }
    
            try {
                FileInputStream fis = new FileInputStream(file);
                ObjectInputStream ois = new ObjectInputStream(fis);
                Singleton_6_MyObject rSingleton = (Singleton_6_MyObject) ois.readObject();
                fis.close();
                ois.close();
                System.out.println(rSingleton.hashCode());
            } catch (FileNotFoundException e) { 
                e.printStackTrace();
            } catch (IOException e) { 
                e.printStackTrace();
            } catch (ClassNotFoundException e) { 
                e.printStackTrace();
            }
    
        }
    }
    

    7.static代码块实现单例

    package testSingletonUnderMultiThreads;
    
    /**
     * @author zhangdi
     * 使用static代码块实现单例,也可以保证线程安全性,也有资源占用问题
     */
    public class Singleton_7_MyObject {
        private static Singleton_7_MyObject MyObject = null;
    
        private Singleton_7_MyObject(){}
    
        static {
            MyObject = new Singleton_7_MyObject();
        }
    
        public static Singleton_7_MyObject getInstance() {
            return MyObject;
        }
    
    }
    

    8.枚举实现单例模式

    package testSingletonUnderMultiThreads;
    
    /**
     * @author zhangdi
     * 使用枚举  缺点 : 但是这样写枚举类的实现细节被完全暴露了,违反了“职责单一原则”?
     */
    public enum Singleton_8_MyObject_enum1 {
        singletonFactory;
    
        private MySingleton instance;
    
        private Singleton_8_MyObject_enum1(){//枚举类的构造方法在类加载是被实例化
            instance = new MySingleton();
        }
    
        public MySingleton getInstance(){
            return instance;
        }
    
    }
    
    class MySingleton{//需要获实现单例的类,比如数据库连接Connection
        public MySingleton(){} 
    }
    

    9.完善的枚举类实现单例模式

    package testSingletonUnderMultiThreads;
    
    /**
     * @author zhangdi
     * 完善使用enum枚举实现单例模式:不暴露枚举类的实现细节  
     */
    public class Singleton_9_MyObject_enum2 {
        //不暴露枚举类的实现细节
        private enum MyEnumSingleton {
            singletonFactory;
    
            private MySingleton2 instance;
    
            private MyEnumSingleton() {// 枚举类的构造方法在类加载时被实例化
                instance = new MySingleton2();
            }
    
            public MySingleton2 getInstance() {
                return instance;
            }
        }
    
        public static MySingleton2 getInstance() {
            return MyEnumSingleton.singletonFactory.getInstance();
        }
    
    }
    
    class MySingleton2 {// 需要获实现单例的类,比如数据库连接Connection
        public MySingleton2() {
        }
    }
    
  • 相关阅读:
    笔记44 Hibernate快速入门(一)
    tomcat 启用https协议
    笔记43 Spring Security简介
    笔记43 Spring Web Flow——订购披萨应用详解
    笔记42 Spring Web Flow——Demo(2)
    笔记41 Spring Web Flow——Demo
    Perfect Squares
    Factorial Trailing Zeroes
    Excel Sheet Column Title
    Excel Sheet Column Number
  • 原文地址:https://www.cnblogs.com/DiZhang/p/12544984.html
Copyright © 2011-2022 走看看