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

    1、立即加载/"饿汉模式"

    立即加载:使用类的时候已经将对象创建完毕,常见的实现办法就是直接new实例化,在调用方法前,实例已经被创建了。

    package com.threadTest.pattern.singleton;
    
    /**
     * Created by sky on 2017/3/22.
     */
    public class MyObject {
        //立即加载方式==饿汉模式
        private static MyObject myObject = new MyObject();
    
        private MyObject() {
        }
    
        public static MyObject getInstance() {
            //代码版本为立即加载
            //此版本代码的缺点是不能有其他实例变量
            //因为getInstance()方法没有同步,所以有可能出现非线程安全问题
            return myObject;
        }
    }
    package com.threadTest.pattern.singleton;
    
    /**
     * Created by sky on 2017/3/22.
     */
    public class MyThread extends Thread{
        @Override
        public void run() {
            System.out.println(MyObject.getInstance().hashCode());
        }
    }
    package com.threadTest.pattern.singleton;
    
    /**
     * Created by sky on 2017/3/22.
     */
    public class Run {
        public static void main(String[] args) {
            MyThread t1 = new MyThread();
            MyThread t2 = new MyThread();
            MyThread t3 = new MyThread();
            t1.start();
            t2.start();
            t3.start();
        }
    }


    输出:
    535693062
    535693062
    535693062

    2、延迟加载/"懒汉模式"

    延迟加载:调用get()方法时实例才被创建,常见的实现办法就是在get()方法中进行new实例化。

    package com.threadTest.pattern.singleton.lazyman;
    
    /**
     * Created by sky on 2017/3/22.
     */
    public class MyObject {
        private static MyObject myObject;
    
        private MyObject() {
        }
    
        public static MyObject getInstance() {
            //延迟加载
            if (null != myObject) {
            } else {
                myObject = new MyObject();
            }
            return myObject;
        }
    }

    延迟加载/"懒汉模式"的缺点:

    package com.threadTest.pattern.singleton.lazyman03;
    
    /**
     * Created by sky on 2017/3/22.
     */
    public class MyObject {
        private static MyObject myObject;
    
        private MyObject() {
        }
    
        //效率低下
        synchronized public static MyObject getInstance() {
            //延迟加载
            if (null != myObject) {
            } else {
                try {
                    //模拟在创建对象之前做一些准备性工作 导致阻塞
                    Thread.sleep(3000);
                    myObject = new MyObject();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
            return myObject;
        }
    }

     使用DCL双检查锁机制

    package com.threadTest.pattern.singleton.lazyman05;
    
    /**
     * Created by sky on 2017/3/22.
     */
    public class MyObject {
        private static MyObject myObject;
    
        private MyObject() {
        }
    
        //效率低下
        public static MyObject getInstance() {
            try {
                //使用双检测机制来解决, 既保证了不需要同步代码的异步执行性,又保证了单例的效果
                if (null != myObject) {
                } else {
                    //模拟在创建对象之前做一些准备性工作 导致阻塞
                    Thread.sleep(3000);
                    synchronized (MyObject.class) {
                        if (null == myObject) {
                            myObject = new MyObject();
                        }
                    }
                }
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            return myObject;
        }
    }

    3、使用静态内置类实现单例模式

    package com.threadTest.pattern.singleton.test01;
    
    /**
     * Created by sky on 2017/3/22.
     */
    public class MyObject {
        //内部类方式
        private static class MyObjectHandler {
            private static MyObject myObject = new MyObject();
        }
        private MyObject(){}
        public static MyObject getInstance(){
            return MyObjectHandler.myObject;
        }
    }

    4、序列化和反序列化单例模式

    package com.threadTest.pattern.singleton.serialize;
    
    import java.io.ObjectStreamException;
    import java.io.Serializable;
    
    /**
     * Created by sky on 2017/3/22.
     */
    public class MyObject implements Serializable {
        private static final long serialVersionUID = 800L;
    
        //内部类方式
        private static class MyObjectHandler {
            private static MyObject myObject = new MyObject();
        }
    
        private MyObject() {
        }
    
        public static MyObject getInstance() {
            return MyObjectHandler.myObject;
        }
    
        //方法readResolve会在ObjectInputStream已经读取一个对象并在准备返回前调用。
        // ObjectInputStream 会检查对象的class是否定义了readResolve方法。
        // 如果定义了,将由readResolve方法指定返回的对象。
        // 返回对象的类型一定要是兼容的,否则会抛出ClassCastException 。 
        protected Object readResolve() throws ObjectStreamException {
            System.out.println("调用了 readResolve方法!");
            return MyObjectHandler.myObject;
        }
    }
    package com.threadTest.pattern.singleton.serialize;
    
    import java.io.*;
    
    /**
     * Created by sky on 2017/3/22.
     */
    public class SaveAndRead {
        public static void main(String[] args) {
            try {
                MyObject myObject = MyObject.getInstance();
                FileOutputStream fosRef = new FileOutputStream(new File("F:/myObjectFile.txt"));
                ObjectOutputStream oosRef = new ObjectOutputStream(fosRef);
                oosRef.writeObject(myObject);
                oosRef.close();
                fosRef.close();
                System.out.println(myObject.hashCode());
            } catch (FileNotFoundException e) {
                e.printStackTrace();
            } catch (IOException e) {
                e.printStackTrace();
            }
    
            try {
                FileInputStream fisRef = new FileInputStream(new File("F:/myObjectFile.txt"));
                ObjectInputStream iosRef = new ObjectInputStream(fisRef);
                //注意myObject 新建的
                MyObject myObject = (MyObject) iosRef.readObject();
                iosRef.close();
                fisRef.close();
                System.out.println(myObject.hashCode());
            } catch (FileNotFoundException e) {
                e.printStackTrace();
            } catch (IOException e) {
                e.printStackTrace();
            } catch (ClassNotFoundException e) {
                e.printStackTrace();
            }
        }
    }


    输出:
    787604730
    调用了 readResolve方法!
    787604730

    5、使用静态代码块实现单例模式

    package com.threadTest.pattern.singleton.static01;
    
    /**
     * Created by sky on 2017/3/22.
     */
    public class MyObject {
        private static MyObject instance = null;
        private MyObject() {}
        //静态代码块中的代码在使用类的时候已经执行了
        static {
            instance = new MyObject();
        }
        public static MyObject getInstance() {
            return instance;
        }
    }

     6、使用enum枚举类型实现单例模式枚举enum和静态代码块的特性相似,在使用枚举时,构造方法会被自动调用

      package com.threadTest.pattern.singleton.enum01;

    import java.sql.Connection;
    import java.sql.DriverManager;
    import java.sql.SQLException;

    /**
    * Created by sky on 2017/3/22.
    */
    public class MyObject {
    public enum MyEnumSingleton {
    connectionFactory;
    private Connection connection;

    private MyEnumSingleton() {
    System.out.println("在使用枚举时,构造方法会被自动调用,调用了MyObject的构造");
    String url = "jdbc:mysql://localhost:3306/test?serverTimezone=UTC";
    String username = "root";
    String password = "yuantu123";
    String driverName = "com.mysql.cj.jdbc.Driver";
    try {
    Class.forName(driverName);
    connection = DriverManager.getConnection(url, username, password);
    } catch (ClassNotFoundException e) {
    e.printStackTrace();
    } catch (SQLException e) {
    e.printStackTrace();
    }
    }

    public Connection getConnection() {
    return connection;
    }
    }

    public static Connection getConnection() {
    return MyEnumSingleton.connectionFactory.getConnection();
    }
    }
      package com.threadTest.pattern.singleton.enum01;

    /**
    * Created by sky on 2017/3/22.
    */
    public class MyThread extends Thread {
    @Override
    public void run() {
    for (int i = 0; i < 5; i++) {
    System.out.println(MyObject.getConnection().hashCode());
    }
    }
    }

    输出:
    调用了MyObject的构造
    9507302
    9507302
    9507302
    9507302
    9507302
    9507302
    9507302
    9507302
    9507302
    9507302
    9507302
    9507302
    9507302
    9507302
    9507302


  • 相关阅读:
    java,时间转时间戳的转换以及各种date格式的转化
    HTML 表单提交 的简单代码
    约瑟夫环是一个数学的应用问题:已知n个人(以编号1,2,3...n分别表示)围坐在一张圆桌周围。从编号为k的人开始报数,数到m的那个人出列;他的下一个人又从1开始报数,数到m的那个人又出列;依此规律重复下去,直到圆桌周围的人全部出列。
    获取json中字段,判断是否有想要的key
    mybatis复习
    Spring整合Struts2 注解版
    Spring整合Struts2 XML版
    struts2
    Struts2入门
    存储过程
  • 原文地址:https://www.cnblogs.com/beaconSky/p/6601547.html
Copyright © 2011-2022 走看看