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

 找回密码
 加入黑马

QQ登录

只需一步,快速开始

本帖最后由 136616244 于 2014-5-7 22:25 编辑
  1. package 多线程;

  2. class 生产者消费者 {
  3.         public static void main(String[] args) {
  4.                 Res r = new Res();
  5.                 boolean flag = false;
  6.                 Producer p = new Producer(r);
  7.                 Consumer c = new Consumer(r);
  8.                 Thread t = new Thread(p);
  9.                 Thread t2 = new Thread(c);
  10.                
  11.                 t.start();
  12.                 t2.start();
  13.         }
  14. }
  15. class Res{
  16.         boolean flag = false;
  17.         int count = 0;
  18.         public synchronized void setResource(){
  19.                 count++;
  20.                 System.out.println(Thread.currentThread().getName()+"生产者------"+count);
  21.         }
  22.         public synchronized void getResource(){
  23.                 System.out.println(Thread.currentThread().getName()+"消费者。。。。。。。。。。。。"+count);
  24.         }
  25. }
  26. class Producer implements Runnable{
  27.         Res r;
  28.         
  29.         Producer(Res r ){
  30.                 this.r = r;

  31.         }
  32.         public void run(){
  33.                 while(true){
  34.                         if(!(r.flag)){
  35.                                 r.setResource();
  36.                                 r.flag =true;
  37.                         }
  38.         
  39.                 }
  40.         }
  41. }
  42. class Consumer implements Runnable{
  43.         Res r;
  44.         Consumer(Res r){
  45.                 this.r = r;

  46.         }
  47.         public void run(){
  48.                 while(true){
  49.                         if(r.flag){
  50.                                 r.getResource();
  51.                                 r.flag =false;
  52.                         }
  53.                 }

  54.         }
  55. }
复制代码

10 个回复

倒序浏览
本帖最后由 136616244 于 2014-5-7 22:25 编辑

其他人有运行有问题的吗,我的机器上会出现两个线程都在等待
回复 使用道具 举报
好像每次运行结果都不太一样

Thread-0生产者------1
Thread-1消费者。。。。。。。。。。。。1
Thread-0生产者------2
Thread-1消费者。。。。。。。。。。。。2
Thread-0生产者------3
Thread-1消费者。。。。。。。。。。。。3
Thread-0生产者------4
Thread-1消费者。。。。。。。。。。。。4
Thread-0生产者------5
Thread-1消费者。。。。。。。。。。。。5
Thread-0生产者------6
Thread-1消费者。。。。。。。。。。。。6
Thread-0生产者------7


每次都是运行了一部分后就卡在那里不动了,哪位大神来看看?
Thread-0生产者------1
Thread-1消费者。。。。。。。。。。。。1
Thread-0生产者------2
Thread-1消费者。。。。。。。。。。。。2
Thread-0生产者------3
Thread-1消费者。。。。。。。。。。。。3
Thread-0生产者------4
Thread-1消费者。。。。。。。。。。。。4
Thread-0生产者------5
Thread-1消费者。。。。。。。。。。。。5
Thread-0生产者------6
Thread-1消费者。。。。。。。。。。。。6
Thread-0生产者------7
Thread-1消费者。。。。。。。。。。。。7
Thread-0生产者------8
Thread-1消费者。。。。。。。。。。。。8
Thread-0生产者------9
Thread-1消费者。。。。。。。。。。。。9
Thread-0生产者------10
Thread-1消费者。。。。。。。。。。。。10
Thread-0生产者------11
Thread-1消费者。。。。。。。。。。。。11
Thread-0生产者------12
Thread-1消费者。。。。。。。。。。。。12
Thread-0生产者------13
Thread-1消费者。。。。。。。。。。。。13
Thread-0生产者------14
Thread-1消费者。。。。。。。。。。。。14
Thread-0生产者------15
Thread-1消费者。。。。。。。。。。。。15
Thread-0生产者------16
Thread-1消费者。。。。。。。。。。。。16
Thread-0生产者------17
Thread-1消费者。。。。。。。。。。。。17
Thread-0生产者------18
Thread-1消费者。。。。。。。。。。。。18
Thread-0生产者------19
Thread-1消费者。。。。。。。。。。。。19
Thread-0生产者------20
Thread-1消费者。。。。。。。。。。。。20
Thread-0生产者------21
Thread-1消费者。。。。。。。。。。。。21
Thread-0生产者------22
Thread-1消费者。。。。。。。。。。。。22
Thread-0生产者------23
Thread-1消费者。。。。。。。。。。。。23
Thread-0生产者------24
Thread-1消费者。。。。。。。。。。。。24
Thread-0生产者------25
Thread-1消费者。。。。。。。。。。。。25
Thread-0生产者------26
Thread-1消费者。。。。。。。。。。。。26
Thread-0生产者------27
Thread-1消费者。。。。。。。。。。。。27
Thread-0生产者------28
Thread-1消费者。。。。。。。。。。。。28
Thread-0生产者------29
Thread-1消费者。。。。。。。。。。。。29
Thread-0生产者------30
Thread-1消费者。。。。。。。。。。。。30
Thread-0生产者------31
Thread-1消费者。。。。。。。。。。。。31
Thread-0生产者------32
Thread-1消费者。。。。。。。。。。。。32
Thread-0生产者------33
Thread-1消费者。。。。。。。。。。。。33
Thread-0生产者------34
Thread-1消费者。。。。。。。。。。。。34
Thread-0生产者------35
Thread-1消费者。。。。。。。。。。。。35
Thread-0生产者------36
Thread-1消费者。。。。。。。。。。。。36
Thread-0生产者------37
Thread-1消费者。。。。。。。。。。。。37
Thread-0生产者------38
Thread-1消费者。。。。。。。。。。。。38
Thread-0生产者------39
Thread-1消费者。。。。。。。。。。。。39
Thread-0生产者------40
Thread-1消费者。。。。。。。。。。。。40
Thread-0生产者------41
Thread-1消费者。。。。。。。。。。。。41
Thread-0生产者------42
Thread-1消费者。。。。。。。。。。。。42
Thread-0生产者------43


回复 使用道具 举报
哎呀   终于能找到能运行的结果跟一样的了
今天下午问了三个同学都说没问题,
回复 使用道具 举报
136616244 发表于 2014-5-7 22:16
其他人有运行有问题的吗,我的机器上会出现两个线程都在等待

哈哈,楼主,我想清楚了, 运行t.start()时, flag=false后, 可能cpu会一直运行这个线程,然后一直在判断, 没有给t2.start()执行的机会, 这样就会出现一种等待的情况, 你在两个if判断语句后都加上
try {
                                                                        Thread.sleep(100);
                                                                } catch (InterruptedException e) {
                                                                        // TODO Auto-generated catch block
                                                                        e.printStackTrace();
                                                                }
让线程在修改flag值后,都睡眠0.1s,这样另外一个线程肯定会执行,不会出现一只等待的情况了,我刚刚试过了,没问题了
回复 使用道具 举报
本帖最后由 136616244 于 2014-5-7 22:44 编辑
张耀扬 发表于 2014-5-7 22:39
哈哈,楼主,我想清楚了, 运行t.start()时, flag=false后, 可能cpu会一直运行这个线程,然后一直在判断, 没有 ...


那这不科学啊   都具备执行资格     cpu的执行权应该是随机跳转的才对啊   不会跳转吗?

回复 使用道具 举报
136616244 发表于 2014-5-7 22:42
那这不科学啊   都具备执行资格     cpu的执行权应该是随机跳转的才对啊   不会跳转吗?

...

多线程就是会相互抢占cpu的资源的,完全有可能是某个线程一直运行啊. 你试了我添加的代码了吗?
回复 使用道具 举报
  1. package day3;

  2. public class Test5 {
  3.         public static void main(String[] args) {
  4.                 Res r = new Res();
  5.                 // boolean flag = false;
  6.                 Producer p = new Producer(r);
  7.                 Consumer c = new Consumer(r);
  8.                 Thread t = new Thread(p);
  9.                 Thread t2 = new Thread(c);

  10.                 t.start();

  11.                 t2.start();
  12.         }
  13. }

  14. class Res {
  15.         boolean flag = false;
  16.         int count = 0;

  17.         public synchronized void setResource() {
  18.                 count++;
  19.                 System.out.println(Thread.currentThread().getName() + "生产者------"
  20.                                 + count);
  21.         }

  22.         public synchronized void getResource() {
  23.                 System.out.println(Thread.currentThread().getName() + "消费者。。。。。。。。。。。。"
  24.                                 + count);
  25.         }
  26. }

  27. class Producer implements Runnable {
  28.         Res r;

  29.         Producer(Res r) {
  30.                 this.r = r;
  31.         }

  32.         public void run() {//因为这里是死循环,只要进来就跳不出去,有可能会出现两个线程交替执行一段时间,但是当flag为true时,这里就死循环了,那cpu不是交替执行线程的吗?难道消费者的线程就一直抢不到执行权吗?就用打印方法验证一下就知道了,发现当加入打印的方法后两个线程还是会有非常小的几率交替执行,当然99.9%的还是死循环的打印方法,所以在两个线程的run方法中加点睡眠时间看看效果,此时将打印的方法都关闭,这时发现生产者生产2商品后程序又死循环了,可以想到这么一种情况,当消费完1号后生产者可以说是瞬间生产2后进入睡眠,之后消费者和生产者可以说是同时醒来,因为生产者是死循环,效率比较快,一直抢得到执行权。为什么这么说,通过打印的方法就可以看到,满屏的pro...out。那也有可能是消费者那里死循环的吧,满屏的cus...out也是可能的?那么把其他的打印语句关掉这里只打开cus...out,又一种神奇的现象出现了,竟然可以看到比较和谐的景象,这又是为什么呢?至此打住!到目前为止答案已经很清晰了,问题就出现在while循环上,那么这里就考虑毕老师视频讲的例子一样,操作资源和标记的事情都交给资源类res去完成,另外在方法中加入wait方法和notify方法实现线程安全和生产消费和谐的画面
  33.                 if (!(r.flag)) {//总结:错误的代码何其多,我们需要的做的就是多使用像打印语句这样调试程序的方法找到问题所在,不必过于深究底层到底谁抢到了cpu,谁没抢到到的情况,毕竟学习的重点不在这种钻牛角尖 的问题,学会 熟练地实现线程安全的做法才是王道
  34.                         r.setResource();
  35.                         r.flag = true;
  36.                         // try {
  37.                         // Thread.sleep(1000);
  38.                         // } catch (InterruptedException e) {
  39.                         // e.printStackTrace();
  40.                         // }
  41.                         // System.out.println("pro....in");
  42.                 }
  43.                 // System.out.println("pro....out");
  44.         }
  45. }

  46. class Consumer implements Runnable {
  47.         Res r;

  48.         Consumer(Res r) {
  49.                 this.r = r;
  50.         }

  51.         public void run() {
  52.                 while (true) {
  53.                         if (r.flag) {
  54.                                 r.getResource();
  55.                                 r.flag = false;
  56.                                 // try {
  57.                                 // Thread.sleep(1000);
  58.                                 // } catch (InterruptedException e) {
  59.                                 // e.printStackTrace();
  60.                                 // }
  61.                                 // System.out.println("cus....in");
  62.                         }
  63.                         // System.out.println("cus....out");
  64.                 }
  65.         }
  66. }
复制代码

评分

参与人数 1技术分 +1 收起 理由
张然龙 + 1 很给力!

查看全部评分

回复 使用道具 举报
  1. /*class Person
  2. {
  3.         String name;
  4.         String str;
  5.         boolean flat =false;
  6. }
  7. class Input implements Runnable
  8. {
  9.         private Person p;
  10.         int in=0;
  11.         Input(Person p)
  12.         {
  13.                 this.p=p;
  14.         }
  15.         public void run()
  16.         {
  17.                 while (true)
  18.                 {
  19.                         synchronized(p)
  20.                         {
  21.                         if (p.flat)
  22.                                 try{p.wait();}catch(Exception e){}
  23.                         if (in==0)
  24.                         {
  25.                                 p.name="xianshng";
  26.                                 p.str="........nan";
  27.                         }
  28.                         else
  29.                         {
  30.                                 p.name="女士";
  31.                                 p.str="....女";
  32.                         }
  33.                         in=(in+1)%2;
  34.                         p.flat = true;
  35.                         p.notify();
  36.                         }
  37.                 }       
  38.         }
  39. }
  40. class Output implements Runnable
  41. {
  42.         private Person p;
  43.         Output(Person p)
  44.         {
  45.                 this.p=p;
  46.         }
  47.         public void run()
  48.         {
  49.                 while (true)
  50.                 {
  51.                         synchronized(p)
  52.                         {
  53.                                 if(!p.flat)
  54.                                         try{p.wait();}catch(Exception e){}
  55.                         System.out.println(p.name+p.str);
  56.                         p.flat = false;
  57.                         p.notify();
  58.                         }
  59.                 }
  60.         }
  61. }
  62. class  ThreadDemo2
  63. {
  64.         public static void main(String[] args)
  65.         {
  66.                 Person p = new Person();
  67.                 Thread t1 = new Thread(new Input(p));
  68.                 Thread t2 = new Thread(new Output(p));
  69.                 t1.start();
  70.                 t2.start();
  71.         }
  72. }*/
  73. //代码优化结果
  74. class Person
  75. {
  76.         private String name;
  77.         private String str;
  78.         private boolean flat =false;
  79.         public synchronized void set(String name,String str)
  80.         {
  81.                 if(flat)
  82.                         try{this.wait();}catch(Exception e){}
  83.                 this.name = name;
  84.                 this.str = str;
  85.                 flat = true;
  86.                 this.notify();
  87.         }
  88.         public synchronized void out()
  89.         {
  90.                 if(!flat)
  91.                         try{this.wait();}catch(Exception e){}
  92.                 System.out.println(name+str);
  93.                 flat = false;
  94.                 this.notify();
  95.         }
  96. }
  97. class Input implements Runnable
  98. {
  99.         private Person p;
  100.         int in=0;
  101.         Input(Person p)
  102.         {
  103.                 this.p=p;
  104.         }
  105.         public void run()
  106.         {
  107.                 while (true)
  108.                 {
  109.                         if (in==0)
  110.                         p.set("nanshi","...nan");
  111.                         else
  112.                         p.set("女士","........女");
  113.                         in=(in+1)%2;
  114.                 }
  115.         }       
  116. }

  117. class Output implements Runnable
  118. {
  119.         private Person p;
  120.         Output(Person p)
  121.         {
  122.                 this.p=p;
  123.         }
  124.         public void run()
  125.         {
  126.                 while (true)
  127.                 {
  128.                         p.out();
  129.                 }
  130.         }
  131. }
  132. class  ThreadDemo2
  133. {
  134.         public static void main(String[] args)
  135.         {
  136.                 Person p = new Person();
  137.                 new Thread(new Input(p)).start();
  138.                 new Thread(new Output(p)).start();
  139.                
  140.         }
  141. }
复制代码
看看我以前的代码吧  可作对比

评分

参与人数 1技术分 +1 收起 理由
张然龙 + 1 神马都是浮云

查看全部评分

回复 使用道具 举报
楼主,你好。我试了你的代码,一直都没有问题。有几处我改了一下。
1、将类Res中的flag初始值改成true也可以正常运行,只不过先运行的是Consumer线程,从0开始。
2、将get与set方法上的synchronized关键字去掉后一样可以正常运行。
3、加了sleep语句,方便观看效果。

class ProducerConsumer {
        public static void main(String[] args) {
                Res r = new Res();
                boolean flag = false;
                Producer p = new Producer(r);
                Consumer c = new Consumer(r);
                Thread t1 = new Thread(p);
                Thread t2 = new Thread(c);
               
                t1.start();
                t2.start();
        }
}
class Res{
        boolean flag = true;
        int count = 0;
        public void setResource(){
                count++;
                System.out.println(Thread.currentThread().getName()+"生产者------"+count);
        }
        public void getResource(){  //synchronized
                System.out.println(Thread.currentThread().getName()+"消费者。。。。。。。。"+count);
        }
}
class Producer implements Runnable{
        Res r;       
        Producer(Res r ){
                this.r = r;

        }
        public void run(){
                while(true){
                        if(!(r.flag)){
                                r.setResource();
                                r.flag = true;
                        }
                }
        }
}
class Consumer implements Runnable{
        Res r;
        Consumer(Res r){
                this.r = r;
        }
        public void run(){
                while(true){
                        try
                        {
                                Thread.sleep(1000);
                        }
                        catch (Exception e)
                        {
                        }
                        if(r.flag){
                                r.getResource();
                                r.flag =false;
                        }
                }
        }
}
你这个程序我觉得还没有涉及到同步问题,所以我将get和set方法上的同步去掉了。如果要用到同步,可看看下面的代码:

我创建了四个线程,两个生产者,两个消费者。这时就会涉及到同步了。
class ProducerConsumer {
        public static void main(String[] args) {
                Res r = new Res();
                boolean flag = false;
                Producer p = new Producer(r);
                Consumer c = new Consumer(r);
                Thread t1 = new Thread(p);
                Thread t2 = new Thread(c);
                Thread t3 = new Thread(p);
                Thread t4 = new Thread(c);
               
                t1.start();
                t2.start();
                t3.start();
                t4.start();
        }
}
class Res{
        boolean flag = false;
        int count = 0;
        public synchronized void setResource(){
                count++;
                System.out.println(Thread.currentThread().getName()+"生产者------"+count);
        }
        public synchronized void getResource(){
                System.out.println(Thread.currentThread().getName()+"消费者。。。。。。。。"+count);
        }
}
class Producer implements Runnable{
        Res r;       
        Producer(Res r ){
                this.r = r;

        }
        public void run(){
                while(true){
                        synchronized (this)   
                        {
                                if(!r.flag){
                                        r.setResource();
                                        r.flag = true;
                                }
                        }
                }
        }
}
class Consumer implements Runnable{
        Res r;
        Consumer(Res r){
                this.r = r;
        }
        public void run(){
                while(true){
                        try
                        {
                                Thread.sleep(1000);
                        }
                        catch (Exception e)
                        {
                        }
                        synchronized (this)
                        {
                                if(r.flag){
                                        r.getResource();
                                        r.flag = false;
                                }
                        }
                }
        }
}

回复 使用道具 举报
表示运行没问题
回复 使用道具 举报
您需要登录后才可以回帖 登录 | 加入黑马