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

 找回密码
 加入黑马

QQ登录

只需一步,快速开始

© て淡莣了陌生 中级黑马   /  2013-4-27 16:50  /  1416 人查看  /  4 人回复  /   0 人收藏 转载请遵从CC协议 禁止商业使用本文

本帖最后由 て淡莣了陌生 于 2013-4-28 08:36 编辑

class Demo1_Notify {
        
        public static void main(String[] args) {
                final Printer p = new Printer();
               
                new Thread(){
                        public void run() {
                                while(true)
                                        try {
                                                p.print1();
                                        } catch(Exception e) {
                                                e.printStackTrace();        
                                        }
                        }        
                }.start();
               
                new Thread(){
                        public void run() {
                                for(;;)
                                        try {
                                                p.print2();
                                        } catch(Exception e) {
                                                e.printStackTrace();        
                                        }
                        }        
                }.start();
               
                new Thread(){
                        public void run() {
                                for(;;)
                                        try {
                                                p.print3();
                                        } catch(Exception e) {
                                                e.printStackTrace();        
                                        }
                        }        
                }.start();
        }
               
}

class Printer {
        private int flag = 1;        

        public synchronized void print1() throws Exception {                        
                if (flag != 1)        
                        wait();
                System.out.print("好");        
                System.out.print("好");        
                System.out.print("学");        
                System.out.print("习");        
                System.out.print("\r\n");        
                flag = 2;               
                notifyAll();                        
        }
        
        public synchronized void print2() throws Exception {
                if (flag != 2)        
                        wait();
                System.out.print("天");        
                System.out.print("天");        
                System.out.print("向");        
                System.out.print("上");        
                System.out.print("\r\n");
                flag = 3;                        
                notifyAll();                        
        }
        
        public synchronized void print3() throws Exception {
                if (flag != 3)               
                        wait();
                System.out.print("A");        
                System.out.print("l");        
                System.out.print("r");        
                System.out.print("e");        
                System.out.print("a");        
                System.out.print("d");        
                System.out.print("\r\n");
                flag = 1;                        
                notifyAll();                        
        }
        
}

这段代码执行后为什么没有按照顺序来打印呢,研究了大半天了都没找出哪里出了问题,哪位大神能指点一下迷津啊,谢谢了啊!!!

点评

建议楼主在适当的地方加上相应的注释,这样以后查看会更清晰些  发表于 2013-4-27 19:41

评分

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

查看全部评分

4 个回复

倒序浏览
本帖最后由 java冬冬 于 2013-4-27 18:21 编辑

代码修改如下:{:soso_e152:}
  1. class Demo1_Notify {

  2. public static void main(String[] args) {
  3. final Printer p = new Printer();

  4. new Thread(){
  5. public void run() {
  6. while(true)
  7. try {
  8. p.print1();
  9. } catch(Exception e) {
  10. e.printStackTrace();
  11. }
  12. }
  13. }.start();

  14. new Thread(){
  15. public void run() {
  16. for(;;)
  17. try {
  18. p.print2();
  19. } catch(Exception e) {
  20. e.printStackTrace();
  21. }
  22. }
  23. }.start();

  24. new Thread(){
  25. public void run() {
  26. for(;;)
  27. try {
  28. p.print3();
  29. } catch(Exception e) {
  30. e.printStackTrace();
  31. }
  32. }
  33. }.start();
  34. }

  35. }

  36. class Printer {
  37. private int flag = 1;

  38. public synchronized void print1() throws Exception {
  39. while (flag != 1)
  40. wait();
  41. System.out.print("好");
  42. System.out.print("好");
  43. System.out.print("学");
  44. System.out.print("习");
  45. System.out.print("\r\n");
  46. flag = 2;
  47. notifyAll();
  48. }

  49. public synchronized void print2() throws Exception {
  50. while (flag != 2)
  51. wait();
  52. System.out.print("天");
  53. System.out.print("天");
  54. System.out.print("向");
  55. System.out.print("上");
  56. System.out.print("\r\n");
  57. flag = 3;
  58. notifyAll();
  59. }

  60. public synchronized void print3() throws Exception {
  61. while(flag != 3)
  62. wait();
  63. System.out.print("A");
  64. System.out.print("l");
  65. System.out.print("r");
  66. System.out.print("e");
  67. System.out.print("a");
  68. System.out.print("d");
  69. System.out.print("\r\n");
  70. flag = 1;
  71. notifyAll();
  72. }

  73. }

复制代码
运行结果:


点评

也建议这位童鞋在适当的地方加上相应的注释,这样以后查看会更清晰些,也可以让别人能看的清晰些  发表于 2013-4-27 19:42

评分

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

查看全部评分

回复 使用道具 举报
本帖最后由 杨同旺 于 2013-4-27 17:55 编辑

把以上代码中的if,全部改为while,便能解决问题,

原因是由于,先打印print1,此时print3等待,

当print1打印完成后,print3恰好被唤醒,此时print3将不会返回去再判断if,而是不再判断直接就打印了,

所以,需要加上while,print3在打印之前,将会回去判断一下while(flag!=3),结果就正确了.

评分

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

查看全部评分

回复 使用道具 举报
本帖最后由 黄玉昆 于 2013-4-27 19:50 编辑

楼上的说的对,补充点:
为什么要用while,那时因为会出现假唤醒的现象,本来没有被notify,
被唤醒了之后没有判断标记,就容易出问题;
给你一个我写的吧:
  1. package cn.itcast.concurrent;
  2. import java.util.concurrent.locks.Condition;
  3. import java.util.concurrent.locks.Lock;
  4. import java.util.concurrent.locks.ReentrantLock;
  5. public class Business {
  6.         /*  *
  7.          * 需求:
  8.          *     有三个线程:一个主线程,两个子线程A,B;
  9.          *     主线程循环20次,A线程循环30次,B循环40次;
  10.          *     如此交替50次;即主---》A---》B;
  11.          * 思路:
  12.          *      可以定义一个锁,在一个锁上获得三个condition分别代表主,A,B;
  13.          *      定义一个int变量:作为一个标记,来标识三个线程是否可以执行;
  14.          *      1---》主 2---》A 3---》B;
  15.          */
  16.         private Lock lock = new ReentrantLock();
  17.         private int flag = 1;
  18.         private Condition main_condition = lock.newCondition();
  19.         private Condition a_condition = lock.newCondition();
  20.         private Condition b_condition = lock.newCondition();
  21.         public void main(int i) {
  22.                 lock.lock();
  23.                 try {
  24.                         while (flag != 1) {
  25.                                 main_condition.await();
  26.                         }
  27.                         for (int j = 0; j < 20; j++) {
  28.                                 System.out.println(Thread.currentThread().getName() + "main loop" + j + "of" + i);
  29.                         }
  30.                         flag=2;
  31.                         a_condition.signal();
  32.                 } catch (InterruptedException e) {
  33.                         e.printStackTrace();
  34.                 }
  35.                 finally {
  36.                         lock.unlock();
  37.                 }
  38.         }
  39.         public void subA(int i) {
  40.                 lock.lock();
  41.                 try{
  42.                         while(flag!=2){
  43.                                 a_condition.await();
  44.                         }
  45.                         for (int j = 0; j < 20; j++) {
  46.                                 System.out.println(Thread.currentThread().getName() + "A loop" + j + "of" + i);
  47.                         }
  48.                         flag=3;
  49.                         b_condition.signal();
  50.                 } catch (InterruptedException e) {
  51.                         e.printStackTrace();
  52.                 }
  53.                 finally{
  54.                         lock.unlock();
  55.                 }
  56.         }
  57.         public void subB(int i) {
  58.                 lock.lock();
  59.                 try{
  60.                         while(flag!=3){
  61.                                 b_condition.await();
  62.                         }
  63.                         for (int j = 0; j < 20; j++) {
  64.                                 System.out.println(Thread.currentThread().getName()  + "B loop" + j + "of" + i);
  65.                         }
  66.                         flag=1;
  67.                         main_condition.signal();
  68.                 } catch (InterruptedException e) {
  69.                         e.printStackTrace();
  70.                 }
  71.                 finally{
  72.                         lock.unlock();
  73.                 }
  74.         }
  75. }
复制代码

点评

建议这位童鞋在适当的代码处加上相应的注释  发表于 2013-4-27 19:52

评分

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

查看全部评分

回复 使用道具 举报
本帖最后由 黄玉昆 于 2013-4-27 19:52 编辑
  1. package cn.itcast.concurrent;
  2. public class ThreeThreadcommunicati {

  3.         public static void main(String[] args) {
  4.                 final Business business = new Business();
  5.                 new Thread(new Runnable() {
  6.                         @Override
  7.                         public void run() {
  8.                                 for (int i = 0; i < 50; i++) {
  9.                                         business.subA(i);
  10.                                 }
  11.                         }
  12.                 }).start();
  13.                 new Thread(new Runnable() {
  14.                         @Override
  15.                         public void run() {
  16.                                 for (int i = 0; i < 50; i++) {
  17.                                         business.subB(i);
  18.                                 }
  19.                         }
  20.                 }).start();
  21.                 for (int i = 0; i < 50; i++) {
  22.                         business.main(i);
  23.                 }
  24.         }
  25. }
复制代码
回复 使用道具 举报
您需要登录后才可以回帖 登录 | 加入黑马