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

    使用懒汉式加载。 最终可以做到 线程安全,延迟加载,效率高的特点。

    package oneDay;
    
    /**
     * 保证一个类仅有一个实例,并提供一个访问它的全局访问点
     * 1:构造方法私有化
     * 2:声明一个本类对象
     * 3:给外部提供一个静态方法获取对象实例
     * <p>
     * <p>
     * 单例设计模式的存在是为了什么?
     * 1:在设计一些工具类的时候,不需要属性这些东西,只需要方法就可以,所以就不掺和对象,只用单例就可以.
     * 2:工具类可能会被频繁调用.
     * 目的是为了节省重复创建对象所带来的内存消耗.从而提高效率.
     * <p>
     * 能不能使用构造方法私有化再加上static 来替代单例?   不能, 构造方法 不能静态化.
     * <p>
     * <p>
     * 在类被加载的时候 因为类中的实例是有 static修饰的,所以当时的实例已经创建好了.
     * 然后继续getIntance的时候  得到的就是 同一个对象.
     */
    public class singleCase {
        public static void main(String[] args) {
    
        }
    }
    
    
    // 饿汉式 : 在类被加载后,对象被创建,到程序结束之后释放.
    class Singleton1 {
        private Singleton1() {
        }
    
        private static Singleton1 s = new Singleton1();
    
        public static Singleton1 getInstance() {
            return s;
        }
    
        public void print() {
            System.out.println("测试方法1!");
        }
    }
    // 懒汉式  : 在第一次调用getInstance方法时,对象被创建,到程序结束后释放.
    // 在多线程访问的时候 可能会因为生命周期的问题  而出现程序崩溃错误.
    // 可能出现 第一个线程进入 getInstance的时候, 发现s为空 , 在没有 声明实例的时候, 第二个进程也发现了 s 为空.  这个时候   实例就变了.
    // 解决方法:
    // 1: 将getInstance加上线程锁, 但是这样的话就是 串行执行了 . 效率的良心大大滴坏了.
    // 2: 还有一种说话 是给 s = new Singleton2(); 加上同步代码块, 但是这样显然没法解决  实例变化的问题. 是个扯淡的方法.
    
    class Singleton2 {
        private Singleton2() {
        }
    
        private static Singleton2 s;
    
        public static Singleton2 getInstance() {
            if (s == null)
                s = new Singleton2();
            return s;
        }
    
        public void print() {
            System.out.println("测试方法2!");
        }
    }
    
    // 3: 结合第二种方法, 实现第三种方法 . 加上同步代码块减少锁影响的颗粒大小, 并且避免第二种方法的问题.  就是在同步代码块中  再次判断是否为空.
    //  双重加锁法.  但是这样还可能会存在问题.  因为牵扯到 JVM实现 s = new Singleton3(); 的指令顺序问题 .
    //  其指令大致分为以下三步:   1 申请一块内存空间用于存放实例内容 2 在该空间实例化对象  3  将该内存地址富裕s
    //  底层执行的时候  不一定是按照123 执行的,  有可能是132 (底层代码速度优化方案.). 这样的话 在没有实例化对象的时候 , s不为null , 这样另一个线程发现s 不为空, 但是拿到的是空的s , 这个时候程序就炸了.
    class Singleton3 {
        private Singleton3() {
        }
    
        private static Singleton3 s;
    
        public static Singleton3 getInstance() {
            if (s == null)
                synchronized (Singleton3.class) {
    				/* 第三种方案对  对二种方法的改进 */
                    if (s == null) {
                        s = new Singleton3();
                    }
                }
            return s;
        }
    
        public void print() {
            System.out.println("测试方法2!");
        }
    }
    // 4: 为了解决第三种方案的缺陷,  我们需要禁止代码重排. 由此而生第四种方案, 这个应该是最完美的方案了.
    class Singleton4 {
    	private Singleton4() {
    	}
    
    	/* 第四种方案对第三种的优化 */
    	private static volatile Singleton4 s;
    
    	public static Singleton4 getInstance() {
    		if (s == null)
    			synchronized (Singleton4.class) {
    				/* 第三种方案对  对二种方法的改进 */
    				if (s == null) {
    					s = new Singleton4();
    				}
    			}
    		return s;
    	}
    
    	public void print() {
    		System.out.println("测试方法2!");
    	}
    }
    

    使用饿汉式配合类装载机制,也可以实现懒加载和线程安全,以及高效。

    public class Singleton {
    
        private Singleton() {}
    
        private static class SingletonInstance {
            private static final Singleton INSTANCE = new Singleton();
        }
    
        public static Singleton getInstance() {
            return SingletonInstance.INSTANCE;
        }
    }
    

    类加载器加载类的时候,会将静态属性直接初始化。 通过这里类加载器的特性, 我们可以做到线程安全。 通过内部类的方式,实现懒加载。

  • 相关阅读:
    51 Nod 1068 Bash游戏v3
    51 Nod Bash 游戏v2
    51 Nod 1073 约瑟夫环
    UVA 12063 Zeros and ones 一道需要好好体会的好题
    51 Nod 1161 Partial sums
    2018中国大学生程序设计竞赛
    UVA 11971 Polygon
    UVA 10900 So do you want to be a 2^n-aire?
    UVA 11346 Possibility
    python with as 的用法
  • 原文地址:https://www.cnblogs.com/A-FM/p/10543245.html
Copyright © 2011-2022 走看看