一、问题背景
单例,大家都应该清楚,面试时也经常被问到,大家也都会写。但就是这个最常规的东西,让我有了新的认识。
问题是这样的,我正准备做一个不同情况时的性能测试。Bean的生成方式就是单例,getInstance()。测试时需要测试并发下代码的正常执行,所以采用多线程方式来调用getInstance()。这时问题来了,发现getInstance()并非真正的单例,被初始化了多次,次数不固定。Why?
二、问题分析
经过研究发现问题是由于高并发导致的,有很大几率导致多个if(instance==null)的判断同时为true,引发重复初始化。
有问题的代码MySingleton(X)
01 |
package org.noahx.singleton; |
02 |
03 |
import java.util.Date; |
04 |
import java.util.concurrent.ExecutorService; |
05 |
import java.util.concurrent.Executors; |
06 |
import java.util.concurrent.TimeUnit; |
07 |
import java.util.concurrent.atomic.AtomicInteger; |
08 |
09 |
/** |
10 |
* Created with IntelliJ IDEA. |
11 |
* User: noah |
12 |
* Date: 4/28/13 |
13 |
* Time: 9:37 PM |
14 |
* To change this template use File | Settings | File Templates. |
15 |
*/ |
16 |
public class MySingleton {
|
17 |
18 |
private static MySingleton mySingleton; |
19 |
20 |
/** |
21 |
* 原子计数器 |
22 |
*/ |
23 |
private static AtomicInteger count= new AtomicInteger( 0 ); |
24 |
25 |
private MySingleton() {
|
26 |
27 |
//模拟长时间初始化 |
28 |
try {
|
29 |
Thread.sleep( 5 ); |
30 |
} catch (InterruptedException e) {
|
31 |
e.printStackTrace(); |
32 |
} |
33 |
System.out.println(count.incrementAndGet()); |
34 |
} |
35 |
36 |
public static MySingleton getInstance() {
|
37 |
if (mySingleton == null ) {
|
38 |
mySingleton = new MySingleton(); |
39 |
} |