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

 找回密码
 加入黑马

QQ登录

只需一步,快速开始

本帖最后由 NewDemo 于 2014-5-8 02:32 编辑

首先是问题代码
  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. }
复制代码
接下来是我调试的过程
  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. }
复制代码






3 个回复

倒序浏览
????????
回复 使用道具 举报
牛人,写这么长的代码,不错
回复 使用道具 举报
不懂啊?帅哥QQ多少啊?
回复 使用道具 举报
您需要登录后才可以回帖 登录 | 加入黑马