单例模式的写法非常多。先给出一种最基础的写法:
(A种写法):
package singleton; public class SingletonInstance { private static SingletonInstance mSingletonInstance = null; // 特意将构造函数设置成 private,防止外部使用者new SingletonInstance()。 private SingletonInstance() { } public static SingletonInstance getInstance() { if (mSingletonInstance == null) { mSingletonInstance = new SingletonInstance(); } return mSingletonInstance; } }
A写法是单例模式最简单、最基础、最清晰的写法。但遗憾的是这样的写法是线程不安全的代码写法。
假设该类同一时候在并发N多个线程中被訪问被使用、尤其是假设这个类假设涉及到数据库訪问等等此类线程安全问题敏感的代码应用场景时,后果将是一场灾难。
但单例模式的A种写法也有其广泛场景:不要求线程安全,没有同步需求且效率优先级高的场景中。推荐使用单例模式的A种写法。
B种写法(线程安全写法1):
package singleton; public class SingletonInstance { private static SingletonInstance mSingletonInstance = null; // 特意将构造函数设置成 private。防止外部使用者new SingletonInstance()。 private SingletonInstance() { } public static synchronized SingletonInstance getInstance() { if (mSingletonInstance == null) { mSingletonInstance = new SingletonInstance(); } return mSingletonInstance; } }
单例模式的B种写法事实上是在A种写法的基础上的改进。要点是添加了同步机制:synchronized。
synchronized ,同步从某种意义上讲事实上就是堵塞,堵塞的结果就是随意时刻,仅仅有一个线程能够訪问该段同步方法体中的代码。这样被synchronized的代码性能将下降,但达到了线程安全的目的。
B种单例模式的写法。主要是为了解决线程安全。
变体非常多。变体的目的主要集中在怎样增强线程安全的操作性。现举比例如以下,比方:
B种写法的增强型变体(线程安全写法2):
package singleton; public class SingletonInstance { // 注意! volatile 也不能全然保证线程安全,后面将写关于volatile的文章解释这一点儿。 // volatile仅仅是增强。 private static volatile SingletonInstance mSingletonInstance = null; // 特意将构造函数设置成 private。防止外部使用者new SingletonInstance()。 private SingletonInstance() { } public static SingletonInstance getInstance() { if (mSingletonInstance == null) { // synchronized (SingletonInstance.class)不必锁住整个方法,仅仅锁住一块代码就可以。 // 和synchronized (this)一样,但由于是static方法。故无法使用this。才使用XXXClass.class // synchronized的基本使用原则:尽可能不要锁住大块大块代码(方法体或类),仅仅锁住必需的一小块核心、急需同步的代码段就可以,越少越好,越小越好。 // 要知道,一旦使用synchronized,就意味着代码性能的开销 synchronized (SingletonInstance.class) { if (mSingletonInstance == null) mSingletonInstance = new SingletonInstance(); } } return mSingletonInstance; } }
时间: 2024-10-24 07:15:10