上一篇博客,Android-Java单例模式,介绍了在真实开发过程中,普遍使用的几种单例模式,而今天这篇博客,将要对单利模式进行优化 并且 通过多线程并发来分析
单利模式的优化:
对于为什么会出现安全问题,可以看Android-多线程安全问题-synchronized,博客
package android.java.thread14; /** * 单例模式优化 */ public class SingletonPattern { private SingletonPattern() { } /** * 俄汉式:多线程并发是安全??的,因为此类一加载就实例化了 */ private static final SingletonPattern SINGLETON_PATTERN = new SingletonPattern(); public static SingletonPattern getInstance1() { return SINGLETON_PATTERN; // 如果这里对SINGLETON_PATTERN共享数据进行操作,多线程并发不安全! } /** * 懒汉式:需要进行 静态方法 synchronized(锁?? SingletonPattern.class) * 此方式性能低:因为线程每次调用此方法都需要判断锁 * 需要明白CPU执行执行多线程的随机性,并用以下代码方式解决 多线程并发 */ private static SingletonPattern singletonPattern = null; public static synchronized SingletonPattern getInstance2() { if (null == singletonPattern) { // 这里对singletonPattern共享数据进行操作,多线程并发不安全! singletonPattern = new SingletonPattern(); // 这里对singletonPattern共享数据进行操作,多线程并发不安全! System.out.println(Thread.currentThread().getName() + ">>>>>>> 懒汉式1 单例模式实例化了"); } return singletonPattern; } /** * 懒汉式:对性能要求高 可以 synchronized + if双重判断 * 需要明白CPU执行执行多线程的随机性,并用以下代码方式解决 多线程并发 */ private static SingletonPattern singleton = null; private static final Object objectLock = new Object(); // 定义一把同步锁?? public static SingletonPattern getInstance3() { if (null == singleton) { synchronized (objectLock) { if (null == singleton) { singleton = new SingletonPattern(); System.out.println(Thread.currentThread().getName() + ">>>>>>> 懒汉式2 单例模式实例化了"); } } } return singleton; } }
多线程并发实例化单例模式:
package android.java.thread14; /** * 执行任务,此任务可以给线程运行 */ class DoRunnable implements Runnable { @Override public void run() { for (int i = 0; i < 1000; i++) { // doRunnable1(); // doRunnable2(); doRunnable3(); try { Thread.sleep(10000); } catch (InterruptedException e) { e.printStackTrace(); } } } private void doRunnable1() { SingletonPattern.getInstance1(); } private void doRunnable2() { SingletonPattern.getInstance2(); } private void doRunnable3() { SingletonPattern.getInstance3(); } } public class Test { public static void main(String[] args) { // 实例化任务 DoRunnable doRunnable = new DoRunnable(); // 开启三个线程 new Thread(doRunnable).start(); new Thread(doRunnable).start(); new Thread(doRunnable).start(); } }
执行结果,CPU随机性:
俄汉式:性能提高的同时 又保证了多线程的并发-安全
/** * 懒汉式:对性能要求高 可以 synchronized + if双重判断 * 需要明白CPU执行执行多线程的随机性,并用以下代码方式解决 多线程并发 */ private static SingletonPattern singleton = null; private static final Object objectLock = new Object(); // 定义一把同步锁?? public static SingletonPattern getInstance3() { // 假设CPU随机第四步:Thread-1 现在判断不为null,进不去 if (null == singleton) { // 假设CPU随机第一步:Thread-0 执行到这里CPU去执行其他Thread-2线程了 假设CPU随机第二步:Thread-2线程在这里判断锁,然后进去了 synchronized (objectLock) { if (null == singleton) { singleton = new SingletonPattern(); System.out.println(Thread.currentThread().getName() + ">>>>>>> 懒汉式2 单例模式实例化了"); } } // 假设CPU随机第三步:Thread-2 执行完毕 } return singleton; }