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

 找回密码
 加入黑马

QQ登录

只需一步,快速开始

© 赵晓东 中级黑马   /  2012-11-24 15:07  /  2046 人查看  /  7 人回复  /   0 人收藏 转载请遵从CC协议 禁止商业使用本文

本帖最后由 Object 于 2012-11-25 17:20 编辑
  1. /*多线程_等待唤醒机制*/

  2. /**
  3. *需求:创建两个线程,一个进行存储信息,一个进行打印信息。
  4. *目的:程序输入一个"mike man"打印一个"mike man"
  5. *           输入一个"莉莉 女女女女女"打印一个"莉莉 女女女女女"
  6. *步骤:创建一个共享资源类RescourceWaitNotifyDemo
  7. *                创建输入线程类InputWaitNotifyDemo
  8. *                创建打印线程类OutputWaitNotifyDemo
  9. *                由主函数创建线程,并执行。
  10. *问题:
  11. *                为什么会有线程安全问题?
  12. *                怎么解决?
  13. */

  14. /*线程共享资源类,信息类*/
  15. class ResourceWaitNotifyDemo //
  16. {
  17.         private String name;
  18.         private String sex;
  19.         private boolean flag=false;


  20.         public synchronized void setInfo(String name,String sex)//信息输入函数
  21.         {
  22.                 if(flag)
  23.                 /*如果flag值为false,则共享资源中没有信息,进行赋值
  24.                   如果为true,则共享资源中有信息没有打印,不进行赋值,进行wait操作
  25.                 */        
  26.                 {
  27.                         try
  28.                         {
  29.                                 this.wait();
  30.                         }
  31.                         catch (Exception e)
  32.                         {
  33.                         }
  34.                 }
  35.                 else
  36.                 {
  37.                         this.name = name;
  38.                         this.sex = sex;                        
  39.                 }        
  40.                 flag=true;         //改变开关,让输入程序不能再次进行赋值,同时可以让打印程序启动
  41.                 this.notify();//唤醒输出线程
  42.         }

  43.         public synchronized void OutInfo()//信息输出函数
  44.         {
  45.                 if (!flag)//如果flag值为ture,则共享资源中有信息,进行打印,否则等待
  46.                 {
  47.                         try
  48.                         {
  49.                                 this.wait();
  50.                         }
  51.                         catch (Exception e)
  52.                         {
  53.                         }
  54.                 }
  55.                 else
  56.                 {
  57.                         System.out.println(name+"......"+sex);                        
  58.                 }               
  59.                 flag=false;        //改变开关,让输入程序可以进行赋值,同时让自己不能在打印
  60.                 this.notify();//唤醒输入线程
  61.         }
  62. }

  63. /*输入线程*/
  64. class InputWaitNotifyDemo implements Runnable
  65. {
  66.         private ResourceWaitNotifyDemo r;        //创建共享类引用

  67.         InputWaitNotifyDemo(ResourceWaitNotifyDemo r)
  68.         {
  69.                 this.r = r;        //接收共享类对象
  70.         }

  71.         public void run()
  72.         {
  73.                 int x=0;
  74.                 while(true)
  75.                 {        
  76.                         if (x==0)
  77.                         {
  78.                                 r.setInfo("mike","man");
  79.                         }
  80.                         else
  81.                         {
  82.                                 r.setInfo("莉莉","女女女女女");
  83.                         }
  84.                         x=(x+1)%2;                                                
  85.                 }
  86.         }

  87. }

  88. /*输出线程*/
  89. class OutputWaitNotifyDemo implements Runnable
  90. {
  91.         private ResourceWaitNotifyDemo r;

  92.         OutputWaitNotifyDemo(ResourceWaitNotifyDemo r)
  93.         {
  94.                 this.r = r;        //和输入线程操作同一个共享类对象
  95.         }

  96.         public void run()
  97.         {
  98.                 while (true)
  99.                 {
  100.                         r.OutInfo();        
  101.                 }
  102.         }
  103. }

  104. /*主函数*/
  105. class ThreadWaitNotifyTest
  106. {
  107.         public static void main(String[] args)
  108.         {
  109.                 ResourceWaitNotifyDemo res = new ResourceWaitNotifyDemo();
  110. /*
  111.                 InputWaitNotifyDemo i = new InputWaitNotifyDemo(res);
  112.                 OutputWaitNotifyDemo o = new OutputWaitNotifyDemo(res);

  113.                 Thread t1 = new Thread(i);
  114.                 Thread t2 = new Thread(o);

  115.                 t1.start();
  116.                 t2.start();
  117. */
  118.                 new Thread(new InputWaitNotifyDemo(res)).start();        //创建输入线程
  119.                 new Thread(new OutputWaitNotifyDemo(res)).start();        //创建打印线程
  120.         }
  121. }
复制代码

PrintPhoto.jpg (227.81 KB, 下载次数: 16)

PrintPhoto.jpg

评分

参与人数 1技术分 +1 收起 理由
刘芮铭 + 1 赞一个!

查看全部评分

7 个回复

倒序浏览
1、为什么会有线程安全问题?
   原因:(1)多线程访问出现延迟(由于共享数据导致);
         (2)线程的随机性(共享数据被多个线程操作)
2、怎么解决?
   (1)同步代码块
        具体格式:synchronized(对象){  需要同步的代码 }
     (2)使用 wait:让线程等待
           notify:唤醒单个线程
           notifyAll:唤醒所有线程

评分

参与人数 1技术分 +1 收起 理由
崔政 + 1 赞一个!

查看全部评分

回复 使用道具 举报
楼主的代码没啥问题啊,应该可以正常运行吧。
回复 使用道具 举报
王阳 发表于 2012-11-24 21:57
楼主的代码没啥问题啊,应该可以正常运行吧。

对啊、他问的问题你没看见啊?
回复 使用道具 举报
代码中可使用while循环。让唤醒的线程再次判断条件。然后使用全唤醒notifyAll。问题即可解决。
回复 使用道具 举报
本帖最后由 Object 于 2012-11-25 17:15 编辑

问题解决掉了。

转自CSDN... 当程序从wait()返回时是什么状态? 是输出线程将信息取走了,运行了notify(),使输入线程继续运行,这时输入线程应该进行赋值操作。而楼主的代码,却有else语句,直接跳过了赋值语句。那它就是保持原来的值,所以会出现连续的相同的值。
把else 去掉即可。
回复 使用道具 举报
王阳 发表于 2012-11-24 21:57
楼主的代码没啥问题啊,应该可以正常运行吧。

有问题,看图片,输入一片输出一片,我预想的是输入一个,输出一个
回复 使用道具 举报
潘天功 发表于 2012-11-24 21:11
1、为什么会有线程安全问题?
   原因:(1)多线程访问出现延迟(由于共享数据导致);
         (2)线 ...

这代码有安全问题。我是让你们帮我解决这代码的问题,不是让你们帮我背定理啊,亲
回复 使用道具 举报
您需要登录后才可以回帖 登录 | 加入黑马