美文网首页
多线程:6单例模式和多线程

多线程:6单例模式和多线程

作者: 81bad73e9053 | 来源:发表于2016-09-04 22:44 被阅读14次

    单例模式和多线程

    1.立即加载

    public class MyObject {
    
        // 立即加载方式==饿汉模式
        private static MyObject myObject = new MyObject();
    
        private MyObject() {
        }
    
        public static MyObject getInstance() {
            // 此代码版本为立即加载
            // 此版本代码的缺点是不能有其它实例变量
            // 因为getInstance()方法没有同步
            // 所以有可能出现非线程安全问题
            return myObject;
        }
    
    }
    
    public class MyThread extends Thread {
    
        @Override
        public void run() {
            System.out.println(MyObject.getInstance().hashCode());
        }
    
    }
    
    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(); 
        }  
    }
    运行结果:
    23945429
    23945429
    23945429
    
    

    2.延迟加载

    2.1 延迟加载不同步在多线程环境下的问题

    public class MyObject {
    
        private static MyObject myObject;
    
        private MyObject() {
        }
    
        public static MyObject getInstance() {
            try {
                if (myObject != null) {
                } else {
                    // 模拟在创建对象之前做一些准备性的工作
                    Thread.sleep(3000);
                    myObject = new MyObject();
                }
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            return myObject;
        }
    
    }
    
    public class MyThread extends Thread {
    
        @Override
        public void run() {
            System.out.println(MyObject.getInstance().hashCode());
        }
    
    }
    
    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(); 
        } 
    }
    运行结果:
    23945429
    1668495
    3729266
    
    

    2.2延迟加载的解决方案

    1.getInstance方法加锁
    2.代码块加锁
    3.重要代码加锁(判断和创建那块加锁)
    4.使用DCL双检查机制

    public class MyObject {
    
        private volatile static MyObject myObject;
    
        private MyObject() {
        }
    
        // 使用双检测机制来解决问题
        // 即保证了不需要同步代码的异步
        // 又保证了单例的效果
        public static MyObject getInstance() {
            try {
                if (myObject != null) {
                } else {
                    // 模拟在创建对象之前做一些准备性的工作
                    Thread.sleep(3000);
                    synchronized (MyObject.class) {
                        if (myObject == null) {
                            myObject = new MyObject();
                        }
                    }
                }
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            return myObject;
        }
        // 此版本的代码称为:
        // 双重检查Double-Check Locking
    
    }
    
    public class MyThread extends Thread {
    
        @Override
        public void run() {
            System.out.println(MyObject.getInstance().hashCode());
        }
    
    }
    
    
    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();
    
        }
    
    }
    

    3.使用静态内部类实现单例模式

    public class MyObject {
    
        // 内部类方式
        private static class MyObjectHandler {
            private static MyObject myObject = new MyObject();
        }
    
        private MyObject() {
        }
    
        public static MyObject getInstance() {
            return MyObjectHandler.myObject;
        }
    
    }
    
    
    public class MyThread extends Thread {
    
        @Override
        public void run() {
            System.out.println(MyObject.getInstance().hashCode());
        }
    
    }
    
    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();
    
        }
    
    }
    

    4.序列化与反序列化单例的实现

    public class MyObject implements Serializable {
    
        private static final long serialVersionUID = 888L;
    
        // 内部类方式
        private static class MyObjectHandler {
            private static final MyObject myObject = new MyObject();
        }
    
        private MyObject() {
        }
    
        public static MyObject getInstance() {
            return MyObjectHandler.myObject;
        }
    
        protected Object readResolve() throws ObjectStreamException {
            System.out.println("调用了readResolve方法!");
            return MyObjectHandler.myObject;
        }
    
    }
    
    public class SaveAndRead {
    
        public static void main(String[] args) {
            try {
                MyObject myObject = MyObject.getInstance();
                FileOutputStream fosRef = new FileOutputStream(new File(
                        "myObjectFile.txt"));
                ObjectOutputStream oosRef = new ObjectOutputStream(fosRef);
                oosRef.writeObject(myObject);
                oosRef.close();
                fosRef.close();
                System.out.println(myObject.hashCode());
            } catch (FileNotFoundException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            } catch (IOException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
    
            try {
                FileInputStream fisRef = new FileInputStream(new File(
                        "myObjectFile.txt"));
                ObjectInputStream iosRef = new ObjectInputStream(fisRef);
                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();
            }
    
        }
    
    }
    

    5.使用static代码块实现单例模式

    public class MyObject {
    
        private static MyObject instance = null;
    
        private MyObject() {
        }
    
        static {
            instance = new MyObject();
        }
    
        public static MyObject getInstance() {
            return instance;
        }
    
    }
    
    public class MyThread extends Thread {
    
        @Override
        public void run() {
            for (int i = 0; i < 5; i++) {
                System.out.println(MyObject.getInstance().hashCode());
            }
        }
    }
    
    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();
    
        }
    
    }
    

    6.使用enum实现单例模式

    public class MyObject {
    
        public enum MyEnumSingleton {
            connectionFactory;
    
            private Connection connection;
    
            private MyEnumSingleton() {
                try {
                    System.out.println("创建MyObject对象");
                    String url = "jdbc:sqlserver://localhost:1079;databaseName=y2";
                    String username = "sa";
                    String password = "";
                    String driverName = "com.microsoft.sqlserver.jdbc.SQLServerDriver";
                    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();
        } 
    }
    
    public class MyThread extends Thread {
    
        @Override
        public void run() {
            for (int i = 0; i < 5; i++) {
                System.out.println(MyObject.getConnection().hashCode());
            }
        }
    }
    
    
    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();
    
        }
    }
    

    相关文章

      网友评论

          本文标题:多线程:6单例模式和多线程

          本文链接:https://www.haomeiwen.com/subject/mhtrettx.html