本帖最后由 郭凯敏 于 2012-7-22 04:33 编辑
首先,单例设计模式分为懒汉和饿汉,懒汉模式由于为了节省资源等,当需要对象时才生成,但是这样会带来线程安全问题,以下是我的代码:
总体的意思是:当线程一刚进入 singleton() 方法,该线程判断完为空后,CPU跳到第二个线程,这时候由于第一个线程还没有生成对象(休眠中),第二个线程也成功判断并且产生了对象;然后CPU又自动调节回到第一个线程,第一个已经在该方法中,且还是按照之前判断的也就是认为st是null,他同样产生一个新的对象;由于new了2个新的对象,所以自然是不同的,我用compare())(自定义的方法)去测试两个值是否相等,结果有时等有时不等(CPU的调节是不规律的,有时候很理想,有时候你懂的...),当不想等时自然违背了单例的初衷,也就产生了安全问题
其实也好解决,加同步就OK,这个地方public static SingleTonLH singleton()写成public static synchronized SingleTonLH singleton()就可以了,只是效率不咋地了
if (st == null) {
st=new SingleTonLH();
}
return st;
}
}
public class SingleTonLhanTest {
public static void main(String[] args) throws Exception {
TestDemo1 test1=new TestDemo1();
TestDemo2 test2=new TestDemo2();
Thread t1=new Thread(test1);
Thread t2=new Thread(test2);
t1.start();
System.out.println(compare());
t2.start();
System.out.println(compare());
}
public static boolean compare() throws Exception
{
return TestDemo1.test()==TestDemo2.test();
}
}
//---------------------------------------------------------------------------------
class SingleTonLH {
private static SingleTonLH st;
private SingleTonLH() {
}
public static SingleTonLH singleton() throws InterruptedException {
if (st == null) {
st=new SingleTonLH();
}
return st;
}
}
//---------------------------------------------------------------------------------
class TestDemo1 implements Runnable {
public static SingleTonLH test() throws Exception
{
SingleTonLH st= SingleTonLH.singleton();
return st;
}
public void run() {
try {
test();
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
//---------------------------------------------------------------------------------
class TestDemo2 implements Runnable {
public static SingleTonLH test() throws Exception
{
SingleTonLH st1= SingleTonLH.singleton();
return st1;
}
public void run() {
try {
test();
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
|