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

    一个栗子:

    public class Singleton {
        private static Singleton uniqueInstance;
        private Singleton() { }
        public static Singleton getInstance() {
            if (uniqueInstance == null) {
                uniqueInstance = new Singleton();
            }
            return uniqueInstance;
        }
    
        public static void main(String[] args) {
            Singleton singleton1 = Singleton.getInstance();
            Singleton singleton2 = Singleton.getInstance();
            System.out.println(singleton1.equals(singleton2));
        }
    }

    注意构造器是private的,然后uniqueInstance是静态的。静态变量记录该类的唯一实例。

    package src.Singleton;
    
    import java.util.concurrent.ExecutorService;
    import java.util.concurrent.Executors;
    
    /**
     * 单例模式确一个类只有一个实例,并提供一个全局访问点
     * 单例模式可以延迟初始化,在药品使用这个对象的时候才去创建它
     */
    
    public class ChocolateBoiler {
        private boolean empty;
        private boolean boiled;
    
        private static ChocolateBoiler uniqueInstance;
    
        private ChocolateBoiler() {
            empty = true;
            boiled = false;
        }
    
        public static ChocolateBoiler getInstance() {
            if (uniqueInstance == null) {
                uniqueInstance = new ChocolateBoiler();
            }
            return uniqueInstance;
        }
    
        private boolean isEmpty() {return empty;}
        private boolean isBoiled() {return boiled;}
    
        public void fill() {
            if (!isEmpty()) {
                empty = false;
                boiled = false;
            }
        }
    
        public void drain() {
            if (!isEmpty() && isBoiled()) {
                empty = true;
            }
        }
    
        public void boil() {
            if (!isEmpty() && !isBoiled()) {
                boiled = true;
            }
        }
    
        public static void main(String[] args) {
            ExecutorService service = Executors.newCachedThreadPool();
            Thread thread = new Thread(){
                public void run() {
                    ChocolateBoiler chocolateBoiler = ChocolateBoiler.getInstance();
                    chocolateBoiler.fill();
                    chocolateBoiler.boil();
                    chocolateBoiler.drain();
                }
            };
            for (int i = 0; i < 5; i++) {
                service.execute(thread);  //2个线程同时执行
            }
            service.shutdown();
        }
    }

    想一想,这会存在什么问题吗?

    是不是任何情况下都只是唯一的实例?当我们遇到多线程的时候,事情可能会变得不一样。

    public class Singleton {
        private static Singleton uniqueInstance;
        private Singleton() { }
        public static synchronized Singleton getInstance() {
            if (uniqueInstance == null) {
                uniqueInstance = new Singleton();
            }
            return uniqueInstance;
        }
    
        public static void main(String[] args) {
            Singleton singleton1 = Singleton.getInstance();
            Singleton singleton2 = Singleton.getInstance();
            System.out.println(singleton1.equals(singleton2));
        }
    }

    解决方法很简单,就是在getinstance方法前加上

    synchronized

    但是这样直接对方法加锁的性能很低。

    一些改进的方案:

    1)对性能要求不高,就私用原来的直接同步方法

    2)不延迟初始化,而是在jvm加载类的时候就创建实例 => 急切初始化

    如果程序一定会创建实例

    public class ThreadSafeSingleton {
        private static ThreadSafeSingleton uniqueInstance = new ThreadSafeSingleton();
        
        private ThreadSafeSingleton() {}
    
        public static ThreadSafeSingleton getInstance() {
            return uniqueInstance;
        }
    }

    3)双重加锁

     性能大大提升

    public class DoubleLockSingleton {
        private volatile static DoubleLockSingleton uniqueInstance;
        
        private DoubleLockSingleton() {}
        
        public static DoubleLockSingleton getInstance() {
            if (uniqueInstance == null) {
                synchronized (DoubleLockSingleton.class) {
                    if (uniqueInstance == null) {
                        uniqueInstance = new DoubleLockSingleton();
                    }
                }
            }
            return uniqueInstance;
        }
    }

    这三种就是线程安全的单例模式的三种形式,各自有各自的适用情况。

  • 相关阅读:
    思念
    Matlab与C++混合编程,添加OpenCV库
    重新启用此博客
    将博客搬至CSDN
    unity探索者之ILRuntime代码热更新
    unity探索者之UGUI圆形图片组件
    unity探索者之UGUI图片描边
    unity探索者之iOS微信登录、分享
    unity探索者之复制内容到剪贴板
    unity探索者之获取设备当前电量
  • 原文地址:https://www.cnblogs.com/shawshawwan/p/9185262.html
Copyright © 2011-2022 走看看