zoukankan      html  css  js  c++  java
  • 单例模式的那些事

    写在前面

      单例Singleton设计模式, 老生常谈的一个设计模式。但你真的用对了么? 用的姿势很重要!

    1.概念解释

      单例顾名思义就是只产生一个实例对象。那怎样保证单一呢?把目标类提供给外部创建实例对象的能力收回,即构造函数设为私有,然后内部提供一个生成实例静态方法。设计成单例模式, 有各种各样的实现方式。

    2.单例模式的设计

    2.1 饿汉式单例

      饿汉式单例是指在方法调用前,实例就已经创建好了。

    -实现代码:

    public class Singleton {
    
        private static Singleton instance = new Singleton();
    
        private Singleton() {
    
        }
    
        public static Singleton getInstance() {
    
            return instance;
        }
    }
    
    

    -验证高并发下的执行情况

    public class SingletonClient {
    
        public static void main(String[] args) throws InterruptedException {
    
            Thread[] threads = new Thread[10];
    
            for (int i = 0; i < 10; i++) {
    
                final Singleton instance = Singleton.getInstance();
    
                threads[i] = new Thread(new Runnable() {
                    @Override
                    public void run() {
                        System.out.println(instance.hashCode());
                    }
                });
            }
    
            for (Thread thread : threads) {
                thread.start();
            }
        }
    }
    
    • 结果
    165827088
    165827088
    165827088
    165827088
    165827088
    165827088
    165827088
    165827088
    165827088
    165827088
    

    2.2 懒汉式单例

    懒汉式单例是指在方法调用获取实例时才创建实例,因为相对饿汉式显得“不急迫”,所以被叫做“懒汉模式”。

    1)单线程的懒汉式单例 -- 初学者最容易犯错的写法.

    public class Singleton {
    
        private static Singleton instance = null;
    
        private Singleton() {
    
        }
    
        public static Singleton getInstance() {
    
            if (instance == null) {
    
                try {
                    // 刻意模仿多线程访问下创建实例不是单一的情况
                    Thread.sleep(100); 
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
    
                instance = new Singleton();
            }
            return instance;
        }
    }
    
    
    

    上面创建单例在单线程下是木问题的。但在多线程访问下就会有问题啦。
    如何改进呢?来,再往下看

    2)线程安全的懒汉式单例.

    -同步方法锁定
      同步方法效率很低, 它把真个方法都加了锁, 在高并发下, 只允许一个线程进入到该方法

    public class Singleton {
    
        private static Singleton instance = null;
    
        private Singleton() {
    
        }
    
        public synchronized static Singleton getInstance() {
    
            if (instance == null) {
    
                instance = new Singleton();
            }
            return instance;
        }
    }
    

    -同步代码块锁定
      同步代码块效率也很低,但比同步方法效率高点, 它把高并发的代码块加了锁, 在高并发下, 只允许一个线程进入到该代码块。

    public class Singleton {
    
        private static Singleton instance = null;
    
        private Singleton() {
    
        }
    
        public static Singleton getInstance() {
    
            try {
    
                synchronized (Singleton.class) {
    
                    if (instance == null) {
    
                        Thread.sleep(100);
    
                        instance = new Singleton();
                    }
                }
            } catch (Exception e) {
    
            }
            return instance;
        }
    }
    

    -双检查锁机制(推荐
    这种方式不仅能保证线性安全, 还能提高效率。因为volatile关键字保证多线程间的可见性;在同步块中使用二次检查,以保证其不被重复实例化。集合其二者,这种实现方式既保证了其高效性,也保证了其线程安全性。

    public class Singleton {
    
        // volatile 关键词修饰
        volatile private static Singleton instance = null;
    
        private Singleton() {
    
        }
    
        public static Singleton getInstance() {
    
            try {
    
                if (instance == null) {
    
                    synchronized (Singleton.class) {
    
                        Thread.sleep(100);
    
                        instance = new Singleton();
                    }
                }
            } catch (Exception e) {
    
            }
            return instance;
        }
    }
    

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

    public class Singleton {
    
        private Singleton() {
    
        }
    
        private static class SingletonHandler {
    
            private static Singleton instance = new Singleton();
        }
    
        public static Singleton getInstance() {
    
            return SingletonHandler.instance;
        }
    }
    

    4)使用静态代码块实现单例模式

    public class Singleton {
    
        private static Singleton instance;
    
        static {
            instance = new Singleton();
        }
    
        private Singleton() {
    
        }
    
    
        public static Singleton getInstance() {
    
            return instance;
        }
    }
    

    写在后面

    新博客

  • 相关阅读:
    -for循环案例(下)
    for循环案例(上)
    for循环
    判断语句案例
    判断语句
    操作符优先级
    windows 下安装图片标注软件 labelling和出错解决
    tf-faster rcnn
    目标检测——Faster R-CNN 详解、Pytorch搭建、训练自己的数据集
    java idea 配置安装
  • 原文地址:https://www.cnblogs.com/chenmo-xpw/p/7056239.html
Copyright © 2011-2022 走看看