A股上市公司传智教育(股票代码 003032)旗下技术交流社区北京昌平校区

 找回密码
 加入黑马

QQ登录

只需一步,快速开始

© 刘海源 中级黑马   /  2012-7-21 18:21  /  1502 人查看  /  2 人回复  /   0 人收藏 转载请遵从CC协议 禁止商业使用本文

要具体代码和解析

2 个回复

倒序浏览
本帖最后由 郭凯敏 于 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();
  }
}
}

回复 使用道具 举报
懒汉式!做俩次判断 效率能好很多
回复 使用道具 举报
您需要登录后才可以回帖 登录 | 加入黑马