黑马程序员技术交流社区

标题: 谁来帮我解决个多线程问题啊 [打印本页]

作者: 嘎路的米    时间: 2015-6-23 23:30
标题: 谁来帮我解决个多线程问题啊
为什么我的程序不能交替打印呢?
弄了好久都弄不出来
  1. class Person {
  2.         String name;
  3.         String sex;
  4.         boolean flag = false;
  5. }

  6. class Input implements Runnable {
  7.         Person p;
  8.         int x = 0;

  9.         public Input(Person p) {
  10.                 this.p = p;
  11.         }

  12.         public void run() {
  13.                 while (true) {
  14.                         synchronized (p) {
  15.                                 while (p.flag)
  16.                                         try {
  17.                                                 p.wait();
  18.                                         } catch (InterruptedException e) {
  19.                                         }
  20.                                 if (x == 0) {
  21.                                         p.name = "张三";
  22.                                         p.sex = "男";
  23.                                 } else {
  24.                                         p.name = "lili";
  25.                                         p.sex = "nv";
  26.                                 }
  27.                                 p.flag = true;
  28.                                 p.notifyAll();
  29.                                 x = (x + 1) % 2;
  30.                         }
  31.                 }
  32.         }
  33. }

  34. class Output implements Runnable {
  35.         Person p;

  36.         public Output(Person p) {
  37.                 this.p = p;
  38.         }

  39.         public void run() {
  40.                 while (true) {
  41.                         synchronized (p) {
  42.                                 while (!p.flag)
  43.                                         try {
  44.                                                 p.wait();
  45.                                         } catch (InterruptedException e) {
  46.                                         }
  47.                                 System.out.println(p.name + "...." + p.sex);
  48.                                 p.flag = false;
  49.                                 p.notifyAll();
  50.                         }
  51.                 }
  52.         }
  53. }

  54. public class Demo {
  55.         public static void main(String[] args) {
  56.                 Person p = new Person();

  57.                 new Thread(new Input(p)).start();
  58.                 new Thread(new Input(p)).start();
  59.                 new Thread(new Output(p)).start();
  60.                 new Thread(new Output(p)).start();

  61.         }
  62. }
复制代码


作者: 白月留梦    时间: 2015-6-24 00:17
目前  只发现while(flag)后面没{}
下面那个也是一样的

作者: 嘎路的米    时间: 2015-6-24 00:51
白月留梦 发表于 2015-6-24 00:17
目前  只发现while(flag)后面没{}
下面那个也是一样的

加了括号也没用
作者: Huan220_欢    时间: 2015-6-24 01:34
p.notifyAll();是唤醒所有线程,包含对方所等待的线程,你不使用同步代码块,使用Lock锁试试看看行不行
作者: 我是隔壁老王呀    时间: 2015-6-24 08:46
本帖最后由 我是隔壁老王呀 于 2015-6-24 08:52 编辑

你确定是你的线程出问题吗?你带上线程名称仔细看看。
线程安全没有问题,这里出现重复输出的现象,是一种巧合
  1. if (x == 0) {
  2.                                         p.name = "张三";
  3.                                         p.sex = "男";
  4.                                 } else {
  5.                                         p.name = "lili";
  6.                                         p.sex = "nv";
  7.                                 }
  8.                                 p.flag = true;
  9.                                 p.notifyAll();
  10.                                 x = (x + 1) % 2;
复制代码

如果在线程2中,x==0,此时输出“张三,男”,当执行完p.notifyAll();还未执行后面的奇偶变换时候,此时线程2切换到线程3,此时x还是0,此时就会输出线程3的“张三,男”,这样就会出现重复的现象,但是他们属于不同的线程,所以没有线程安全问题。
作者: 我是隔壁老王呀    时间: 2015-6-24 08:58
你要是想看出效果,可以在输出后面加一个可变的量作为区别
  1. public void run() {
  2.             int temp = 0;
  3.             while (true) {
  4.                     synchronized (p) {
  5.                             while (!p.flag)
  6.                                     try {
  7.                                             p.wait();
  8.                                     } catch (InterruptedException e) {
  9.                                     }
  10.                             System.out.println(p.name + "...." + p.sex
  11.                                             +"------->" + (temp++));
  12.                             p.flag = false;
  13.                             p.notifyAll();
  14.                     }
  15.             }
复制代码

这样就看的很清楚了。
作者: guiqulaixi    时间: 2015-6-24 10:08
楼主 你的程序本来就实现了交替输入和打印这个事情,但是,你的x变量是线程的私有变量,线程判断x是否为0或1就是在线程自己的范围内判断的,你仔细想想就知道为啥重复打印两次了 我帮你改了下程序,这里会输出你想要的结果
  1. class Person {
  2.         String name;
  3.         String sex;
  4.         boolean flag = false;
  5.                 int x = 0;
  6. }

  7. class Input implements Runnable {
  8.         Person p;
  9.         

  10.         public Input(Person p) {
  11.                 this.p = p;
  12.         }

  13.         public void run() {
  14.                 while (true) {
  15.                         synchronized (p) {
  16.                                 while (p.flag)
  17.                                         try {
  18.                                                 p.wait();
  19.                                         } catch (InterruptedException e) {
  20.                                         }
  21.                                 if (p.x == 0) {
  22.                                         p.name = "张三";
  23.                                         p.sex = "男";
  24.                                 } else {
  25.                                         p.name = "lili";
  26.                                         p.sex = "nv";
  27.                                 }
  28.                                                                 p.x = (p.x + 1) % 2;
  29.                                 p.flag = true;
  30.                                 p.notifyAll();

  31.                         }
  32.                 }
  33.         }
  34. }
复制代码

作者: guiqulaixi    时间: 2015-6-24 10:10
我是隔壁老王呀 发表于 2015-6-24 08:46
你确定是你的线程出问题吗?你带上线程名称仔细看看。
线程安全没有问题,这里出现重复输出的现象,是一种 ...

这不是巧合,无论你测试多少遍,都会是这个结果,原因是楼主把判断交替输出的变量当成了线程的私有变量
作者: JJJD    时间: 2015-6-24 11:27
都是大神!学习啦。。。
作者: 我是隔壁老王呀    时间: 2015-6-24 11:39
guiqulaixi 发表于 2015-6-24 10:10
这不是巧合,无论你测试多少遍,都会是这个结果,原因是楼主把判断交替输出的变量当成了线程的私有变量 ...

嗯,学习了。




欢迎光临 黑马程序员技术交流社区 (http://bbs.itheima.com/) 黑马程序员IT技术论坛 X3.2