java单例模式在多线程环境下的测试,进攻自己学习和复习用.
1. 不加双重判断, 会生成2个不同的对象. 代码如下:
package com.thred;
import java.util.Date;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
public class TestSingleton {
private static TestSingleton s = null;
private TestSingleton() {}
public static TestSingleton getInstance() {
if (s == null) {
System.out.println( new Date() + " " + Thread.currentThread().getName() + "-1->" + s);
try {
Thread.sleep(1);
System.out.println( new Date() + " " + Thread.currentThread().getName() + "-2->" + s);
} catch (InterruptedException e) {
e.printStackTrace();
}
synchronized (TestSingleton.class){
//if(s == null){
System.out.println( new Date() + " " + Thread.currentThread().getName() + "-3->" + s);
s = new TestSingleton();
System.out.println( new Date() + " " + Thread.currentThread().getName() + "-4->" + s);
//}else{
// System.out.println("s isn't null");
//}
}
}
return s;
}
/**
* @param args
*/
public static void main(String[] args) throws Exception{
ExecutorService service = Executors.newFixedThreadPool(10);
for(int i = 0 ;i < 2;i++){
service.submit(new Runnable(){
public void run(){
String str = new Date() +" " + Thread.currentThread().getName() + "-run invoke->" + TestSingleton.getInstance().toString();
System.out.println(str);
}
});
}
}
}
测试结果,会生成2个不同的对象,不是单例,在第四步的没加判断会new 对象.
Mon Jul 23 22:22:54 CST 2012 pool-1-thread-1-1->null
Mon Jul 23 22:22:54 CST 2012 pool-1-thread-2-1->null
Mon Jul 23 22:22:54 CST 2012 pool-1-thread-1-2->null
Mon Jul 23 22:22:54 CST 2012 pool-1-thread-1-3->null
Mon Jul 23 22:22:54 CST 2012 pool-1-thread-1-4->com.thred.TestSingleton@fa7e74
Mon Jul 23 22:22:54 CST 2012 pool-1-thread-1-run invoke->com.thred.TestSingleton@fa7e74
Mon Jul 23 22:22:54 CST 2012 pool-1-thread-2-2->com.thred.TestSingleton@fa7e74
Mon Jul 23 22:22:54 CST 2012 pool-1-thread-2-3->com.thred.TestSingleton@fa7e74
Mon Jul 23 22:22:54 CST 2012 pool-1-thread-2-4->com.thred.TestSingleton@133796
Mon Jul 23 22:22:54 CST 2012 pool-1-thread-2-run invoke->com.thred.TestSingleton@133796
2.加双重判断: 在同步代码块中加入判断,只贴出不同的部分.
synchronized (TestSingleton.class){
if(s == null){
System.out.println( new Date() + " "
+ Thread.currentThread().getName() + "-3->" + s);
s = new TestSingleton();
System.out.println( new Date() + " "
+ Thread.currentThread().getName() + "-4->" + s);
}else{
System.out.println("s isn't null");
}
}
测试结果: 返回同一个对象,是单例
Mon Jul 23 22:27:11 CST 2012 pool-1-thread-2-1->null
Mon Jul 23 22:27:11 CST 2012 pool-1-thread-1-1->null
Mon Jul 23 22:27:11 CST 2012 pool-1-thread-2-2->null
Mon Jul 23 22:27:11 CST 2012 pool-1-thread-2-3->null
Mon Jul 23 22:27:11 CST 2012 pool-1-thread-2-4->com.thred.TestSingleton@183f74d
Mon Jul 23 22:27:11 CST 2012 pool-1-thread-2-run invoke->com.thred.TestSingleton@183f74d
Mon Jul 23 22:27:11 CST 2012 pool-1-thread-1-2->com.thred.TestSingleton@183f74d
s isn't null
Mon Jul 23 22:27:11 CST 2012 pool-1-thread-1-run invoke->com.thred.TestSingleton@183f74d
结论:在写单例的时候一定要加上双重判断呀~~切记