主要介绍单例模式的一种写法、注意事项、作用、测试,以Java语言为例,下面代码是目前见过最好的写法:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 |
public class Singleton { private static volatile Singleton instance = null; // private constructor suppresses private Singleton(){ } public static Singleton getInstance() { // if already inited, no need to get lock everytime if (instance == null) { synchronized (Singleton.class) { if (instance == null) { instance = new Singleton(); } } } return instance; } } |
1、需要注意的点
其中需要注意的点主要有三点
(1) 私有化构造函数
(2) 定义静态的Singleton instance对象和getInstance()方法
(3) getInstance()方法中需要使用同步锁synchronized (Singleton.class)防止多线程同时进入造成instance被多次实例化
可以看到上面在synchronized (Singleton.class)外又添加了一层if,这是为了在instance已经实例化后下次进入不必执行synchronized (Singleton.class)获取对象锁,从而提高性能。
Ps: 也有实现使用的是private static Object obj = new Object();加上synchronized(obj),实际没有必要多创建一个对象。synchronized(X.class) is used to make sure that there is exactly one Thread in the block.
2、单例的作用
单例主要有两个作用
(1) 保持程序运行过程中该类始终只存在一个示例
(2) 对于new性能消耗较大的类,只实例化一次可以提高性能
3、单例模式测试
单例模式可以使用多线程并发进行测试,代码如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 |
public static void main(String[] args) { final CountDownLatch latch = new CountDownLatch(1); int threadCount = 1000; for (int i = 0; i < threadCount; i++) { new Thread() { @Override public void run() { try { // all thread to wait latch.await(); } catch (InterruptedException e) { e.printStackTrace(); } // test get instance System.out.println(Singleton.getInstance().hashCode()); } }.start(); } // release lock, let all thread excute Singleton.getInstance() at the same time latch.countDown(); } |
其中CountDownLatch latch为闭锁,所有线程中都用latch.await();等待锁释放,待所有线程初始化完成使用latch.countDown();释放锁,从而达到线程并发执行Singleton.getInstance()的效果。
1
voletile 这个关键字能详细通俗说下嘛?其实看了不少博客,说的都不怎么明白,云里雾里的。
voletile 这个关键字能详细通俗说下嘛?
public static Singleton getInstance() {
// if already inited, no need to get lock everytime
if (instance == null) {
synchronized (Singleton.class) {
内层的同步 是多余的,因为 public static 就是类级别的同步方法了。
七种实现方法用途广泛
public class Singleton { private static Singleton instance = new Singleton(); private Singleton(){ } public static Singleton getInstance() { return instance; } }楼主看看这个写法靠谱不?
靠谱,用的是 jvm 的初始话机制,不好的地方就是没有延迟加载,类加载时候示例就已经创建
我印象当中Effective Java就是用这种写法,这种写法也是类加载时才创建对象,因为对象的初始化就是在static字段或方法调用、new、还有反射才会初始。可能是因为这种方法实例化时缺少同步吧?
我常见写法偏向是:public class AppStateProvider { private AppStateProvider() {} private static class AppStateProviderHolder { private static AppStateProvider appStateProvider = new AppStateProvider(); } public static AppStateProvider getInstance() { return AppStateProviderHolder.appStateProvider; }}
嗯,我也准备好好看看Effective Java上介绍的各种方式的优劣
Effective Java上说最好的单例是使用枚举,不知道博主是否有所研究?
嗯,是的,有七种写法,不同场景有不同场景的需求
用枚举,防止反序列化new了对象
Pingback: cnblogs: 单例模式的标准写法、注意事项、作用及测试 – Trinea 易站|工作室 | 易站|工作室