七种单例模式的写法

情到浓时终转凉″ 提交于 2020-03-12 12:20:15

七种单例模式的写法

  1. 饿汉式

    特点:在类加载时实例化,线程安全,如果没有使用instance的话比较耗费资源

    class SingletonDemo {
        private static volatile SingletonDemo instance = new SingletonDemo();
    
        private SingletonDemo() {
            System.out.println("构造方法被调用了 " + Thread.currentThread().getName());
        }
    
        public static SingletonDemo getInstance() {
            return instance;
        }
    }
    
  2. 懒汉式(非线程安全)

    特点: 使用时再实例化

    class SingletonDemo {
        private static volatile SingletonDemo instance = null;
    
        private SingletonDemo() {
            System.out.println("构造方法被调用了 " + Thread.currentThread().getName());
        }
    
        public static SingletonDemo getInstance() {
            if (instance == null) {
                instance = new SingletonDemo();
            }
            return instance;
        }
    }
    
  3. 懒汉式(线程安全)

    特点:线程安全,使用synchronized关键字锁方法,多线程的情况下方法使用次数很多的话会严重影响效率

    class SingletonDemo {
        private static volatile SingletonDemo instance = null;
    
        private SingletonDemo() {
            System.out.println("构造方法被调用了 " + Thread.currentThread().getName());
        }
    
        public static synchronized SingletonDemo getInstance() {
            if (instance == null) {
                instance = new SingletonDemo();
            }
            return instance;
        }
    }
    
  4. 饿汉(变种)

    跟上面的饿汉的区别仅是写法 初始化代码写在了静态代码块

    class SingletonDemo {
        private static volatile SingletonDemo instance = null;
    	static {
            instance = new SingletonDemo();
        }
        private SingletonDemo() {
            System.out.println("构造方法被调用了 " + Thread.currentThread().getName());
        }
    
        public static SingletonDemo getInstance() {
            return instance;
        }
    }
    
  5. 懒汉(静态内部类)

    特点:线程安全, 用时加载,使用静态内部类

    class SingletonDemo {
        private static class InnerClass {
            private static final SingletonDemo instance = new SingletonDemo();
        }
        
        private SingletonDemo() {}
        public SingletonDemo getInstance() {
            return InnerClass.instance;
        }
    }
    
  6. 饿汉(枚举)

    利用枚举

    enum SingletonDemo {
        INSTANCE;
    	public void someMethod() {
            sout("enum Singleton");
        }
    }
    
  7. 懒汉(DCL)

    public class VolatileDemo {
        public static void main(String[] args) {
         for (int i = 0; i < 10; i++) {
                new Thread(() -> {
                    SingletonDemo.getInstance();
                }, String.valueOf(i)).start();
            }
    
        }
    }
    
    
    class SingletonDemo {
        private static volatile SingletonDemo instance = null;
    
        private SingletonDemo() {
            System.out.println("构造方法被调用了 " + Thread.currentThread().getName());
        }
    
        public static SingletonDemo getInstance() {
            if (instance == null) {
                synchronized (SingletonDemo.class) {
                    if (instance == null) {
                        instance = new SingletonDemo();
                    }
                }
            }
            return instance;
        }
    }
    

对比

  • 根据实例化时机

  • 根据是否线程安全

    是否线程安全 方式
    饿汉式 线程安全 饿汉式
    懒汉式(非线程安全) 非线程安全 懒汉式
    懒汉式(线程安全) 线程安全 懒汉式
    饿汉(变种) 线程安全 饿汉式
    懒汉(静态内部类) 线程安全 懒汉式
    饿汉(枚举) 线程安全 饿汉式
    懒汉(DCL) 线程安全 懒汉式
标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!