使用懒汉式加载。 最终能够作到 线程安全,延迟加载,效率高的特色。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; } }
类加载器加载类的时候,会将静态属性直接初始化。 经过这里类加载器的特性, 咱们能够作到线程安全。 经过内部类的方式,实现懒加载。安全