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

 找回密码
 加入黑马

QQ登录

只需一步,快速开始

© 潘廖明 中级黑马   /  2013-4-22 00:04  /  2021 人查看  /  8 人回复  /   0 人收藏 转载请遵从CC协议 禁止商业使用本文

本帖最后由 潘廖明 于 2013-4-23 15:26 编辑

一、源程序:
  1. package xiancheng;

  2. public class YouhuaThreadCommunity
  3. {
  4.         /*
  5.          * 线程通讯:其实就是多个线程操作同一块资源,但是操作的行为不同
  6.          *  需求:一个人往箱子里装东西,一个人往箱子取东西。
  7.          *  东西:Res{name,sex;}
  8.          * 输入类:Input{Res,run()}
  9.          * 输出类: Oupt{Res,run()}
  10.          */
  11.         public static void main(String[] args)
  12.         {
  13.                 Res1 r = new Res1();
  14.                 Input1 in = new Input1(r);
  15.                 Output1 out = new Output1(r);
  16.                 new Thread(in).start();
  17.                 new Thread(out).start();
  18.                 Input1 in1 = new Input1(r);
  19.                 Output1 out1 = new Output1(r);
  20.                 new Thread(in1).start();
  21.                 new Thread(out1).start();
  22.         }
  23. }

  24. /*
  25. * 实现资源输出
  26. */
  27. class Input1 implements Runnable
  28. {
  29.         Res1 res;

  30.         /**
  31.          * 初始化资源
  32.          *
  33.          * @param r
  34.          */
  35.         public Input1(Res1 r)
  36.         {
  37.                 this.res = r;
  38.         }

  39.         /*
  40.          * 复写run()方法,生产资源
  41.          */
  42.         @Override
  43.         public void run()
  44.         {
  45.                 int x = 0;
  46.                 while (true)
  47.                 {
  48.                         res.setName("coke", "man");
  49.                         res.setName("笑话", "女");
  50.                 }

  51.         }

  52. }

  53. class Output1 implements Runnable
  54. {

  55.         Res1 res;

  56.         /*
  57.          * 初始化输出资源
  58.          */
  59.         public Output1(Res1 r)
  60.         {
  61.                 this.res = r;
  62.         }

  63.         /*
  64.          * 复写run()方法,消费资源
  65.          */
  66.         @Override
  67.         public void run()
  68.         {

  69.                 while (true)
  70.                 {
  71.                         res.show();
  72.                 }

  73.         }
  74. }

  75. class Res1
  76. {
  77.         private String name;
  78.         private String sex;
  79.         private boolean flag = false;

  80.         /**
  81.          * 设置资源的name与sex的值。
  82.          *  模拟生产资源
  83.          *
  84.          * @param name
  85.          * @param sex
  86.          */
  87.         public synchronized void setName(String name, String sex)
  88.         {
  89.                 while (flag)
  90.                         try
  91.                         {
  92.                                 this.wait();//冻结
  93.                         } catch (InterruptedException e)
  94.                         {
  95.                                 e.printStackTrace();
  96.                         }
  97.                 this.name = name;
  98.                 this.sex = sex;
  99.                 flag = true;
  100.                 this.notifyAll();//唤醒全部冻结线程
  101.         }

  102.         /**
  103.          * 模拟消费资源
  104.          */
  105.         public synchronized void show()
  106.         {
  107.                 while (!flag)
  108.                         try
  109.                         {
  110.                                 this.wait();//冻结
  111.                         } catch (InterruptedException e)
  112.                         {
  113.                                 e.printStackTrace();
  114.                         }
  115.                 System.out.println(name + "---消费---" + sex);
  116.                 flag = false;
  117.                 this.notifyAll();//唤醒全部冻结线程

  118.         }

  119. }
复制代码
二、问题如下:
为什么第一句输出“笑话---消费---女”不是成对的出现?
笑话---消费---女
coke---消费---man
coke---消费---man
笑话---消费---女
笑话---消费---女
coke---消费---man
coke---消费---man
笑话---消费---女
笑话---消费---女

评分

参与人数 1技术分 +1 收起 理由
张熙韬 + 1

查看全部评分

8 个回复

倒序浏览
main函数里面这样写:
  1.                 Res1 r = new Res1();
  2.                 Input1 in = new Input1(r);
  3.                 Output1 out = new Output1(r);
  4.                 new Thread(in).start();
  5.                 new Thread(out).start();
  6.                
  7.                 Res1 r1 = new Res1();
  8.                 Input1 in1 = new Input1(r1);
  9.                 Output1 out1 = new Output1(r1);
  10.                 new Thread(in1).start();
  11.                 new Thread(out1).start();
复制代码
两个不同的消费关系应该使用两个不同的资源

评分

参与人数 1技术分 +1 收起 理由
黄玉昆 + 1

查看全部评分

回复 使用道具 举报
  1. package xiancheng;

  2. public class YouhuaThreadCommunity
  3. {
  4.         /*
  5.          * 线程通讯:其实就是多个线程操作同一块资源,但是操作的行为不同
  6.          *  需求:一个人往箱子里装东西,一个人往箱子取东西。
  7.          *  东西:Res{name,sex;}
  8.          * 输入类:Input{Res,run()}
  9.          * 输出类: Oupt{Res,run()}
  10.          */此处Output
复制代码

改完后运行下没事了

评分

参与人数 1技术分 +1 收起 理由
黄玉昆 + 1

查看全部评分

回复 使用道具 举报
本帖最后由 wodeairenw 于 2013-4-23 01:37 编辑

你建立了两个输入线程,两个取出线程,你可以定义一下线程的名称获取String name =Thread.currentThread().getName();,就会知道原理了。
如果想成对出现的话,加要加入wait() notifiyall()方法。等待唤醒机制。让输入线程输入后等待,输出线程输出,就可以了。直接去看毕老师的等待唤醒机制的视频

评分

参与人数 1技术分 +1 收起 理由
黄玉昆 + 1

查看全部评分

回复 使用道具 举报
肖川 发表于 2013-4-22 23:47
main函数里面这样写:两个不同的消费关系应该使用两个不同的资源

本来就是要解决共享资源的问题。你这样分开没意思了!
回复 使用道具 举报
wodeairenw 发表于 2013-4-23 01:35
你建立了两个输入线程,两个取出线程,你可以定义一下线程的名称获取String name =Thread.currentThread(). ...

代码就是从老师那里看的,老师那边运行没事,怎么我的就是第一句没有匹配的?
回复 使用道具 举报
潘廖明 发表于 2013-4-23 01:44
代码就是从老师那里看的,老师那边运行没事,怎么我的就是第一句没有匹配的? ...

等等,我也没仔细看着代码,我先运行下,
回复 使用道具 举报
本帖最后由 wodeairenw 于 2013-4-23 02:39 编辑
潘廖明 发表于 2013-4-23 01:44
代码就是从老师那里看的,老师那边运行没事,怎么我的就是第一句没有匹配的? ...

你不该调用两次设置名称的方法。。。。这样一搞我也糊涂了,为什么打印会出现这种情况,应该是只打印后面设置的名称的啊,照理应该不会出现coke", "man‘的啊,我加了线程名称了。你自己去看看吧
  1. <p>class YouhuaThreadCommunity
  2. {
  3.         /*
  4.          * 线程通讯:其实就是多个线程操作同一块资源,但是操作的行为不同
  5.          *  需求:一个人往箱子里装东西,一个人往箱子取东西。
  6.          *  东西:Res{name,sex;}
  7.          * 输入类:Input{Res,run()}
  8.          * 输出类: Oupt{Res,run()}
  9.          */
  10.         public static void main(String[] args)
  11.         {
  12.                 Res1 r = new Res1();
  13.                 Input1 in = new Input1(r);
  14.                 Output1 out = new Output1(r);
  15.                 new Thread(in).start();//0线程
  16.                 new Thread(out).start();//1线程
  17.                 Input1 in1 = new Input1(r);
  18.                 Output1 out1 = new Output1(r);
  19.                 new Thread(in1).start();//2线程
  20.                 new Thread(out1).start();//3线程
  21.         }
  22. }</p><p>/*
  23. * 实现资源输出
  24. */
  25. class Input1 implements Runnable
  26. {
  27.         Res1 res;</p><p>        /**
  28.          * 初始化资源
  29.          *
  30.          * @param r
  31.          */
  32.         public Input1(Res1 r)
  33.         {
  34.                 this.res = r;
  35.         }</p><p>        /*
  36.          * 复写run()方法,生产资源
  37.          */
  38.         @Override
  39.         public void run()
  40.         {
  41.                 int x = 0;
  42.                 while (true)
  43.                 {
  44.                         //res.setName("coke", "man");
  45.                         res.setName("笑话", "女");
  46.                 }</p><p>        }</p><p>}</p><p>class Output1 implements Runnable
  47. {</p><p>        Res1 res;</p><p>        /*
  48.          * 初始化输出资源
  49.          */
  50.         public Output1(Res1 r)
  51.         {
  52.                 this.res = r;
  53.         }</p><p>        /*
  54.          * 复写run()方法,消费资源
  55.          */
  56.         @Override
  57.         public void run()
  58.         {
  59.    
  60.                 while (true)
  61.                 {
  62.                         res.show();
  63.                 }</p><p>        }
  64. }</p><p>class Res1
  65. {
  66.         private String name;
  67.         private String sex;
  68.         private boolean flag = false;</p><p>        /**
  69.          * 设置资源的name与sex的值。
  70.          *  模拟生产资源
  71.          *
  72.          * @param name
  73.          * @param sex
  74.          */
  75.         public synchronized void setName(String name, String sex)
  76.         {
  77.    
  78.                 while (flag)
  79.                         try
  80.                         {
  81.                                 this.wait();//冻结
  82.                         } catch (InterruptedException e)
  83.                         {
  84.                                 e.printStackTrace();
  85.                         }
  86.                 this.name = name;
  87.                 this.sex = sex;
  88.     System.out.println(Thread.currentThread().getName()+"在设置。。");
  89.                 flag = true;
  90.                 this.notifyAll();//唤醒全部冻结线程
  91.         }</p><p>        /**
  92.          * 模拟消费资源
  93.          */
  94.         public synchronized void show()
  95.         {
  96.                 while (!flag)
  97.                         try
  98.                         {
  99.                                 this.wait();//冻结
  100.                         } catch (InterruptedException e)
  101.                         {
  102.                                 e.printStackTrace();
  103.                         }
  104.                 System.out.println(name + "------" + sex+"..."+Thread.currentThread().getName());
  105.                 flag = false;
  106.                 this.notifyAll();//唤醒全部冻结线程</p><p>        }</p><p>}</p>
复制代码
回复 使用道具 举报
肖川 中级黑马 2013-4-23 08:25:58
9#
潘廖明 发表于 2013-4-23 01:42
本来就是要解决共享资源的问题。你这样分开没意思了!

你多运行几次就会得到不同的结果。可能与你的cpu运行速度有关,你一个生产者生产出来后还没来得及消费就开始了第二个生产.....
回复 使用道具 举报
您需要登录后才可以回帖 登录 | 加入黑马