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

 找回密码
 加入黑马

QQ登录

只需一步,快速开始

本帖最后由 何明辉 于 2012-9-7 14:25 编辑

class Ticket
{
private String name;
public int count=0;
public void set(String name)
{
  this.name=name;
}
public String get()
{
  return this.name;
}
}
class TicketRun implements Runnable
{
private Ticket tc;
boolean flag=false;
TicketRun(Ticket tc)
{
  this.tc=tc;
}
public void run()
{
  if(Thread.currentThread().getName()=="输入线程")
  {
   while(true)
   {
    synchronized(tc)
    {
     if(flag) try{wait();}catch (Exception e){}
   
     tc.set("HeMingHui");
     System.out.println(Thread.currentThread().getName()+tc.get()+tc.count++);
     flag=true;
     this.notify();
    }
   }
  }
  else
   while(true)
  {
   synchronized(tc)
   {
    if(!flag)try{wait();}catch(Exception e){}
  
    System.out.println(Thread.currentThread().getName()+tc.get()+tc.count);
    flag=false;
       this.notify();
   }
  }
}
}
class TicketDemo
{
public static void main(String[] args)
{
   Ticket tc=new Ticket();
   TicketRun p=new TicketRun(tc);
   Thread t1=new Thread(p,"输入线程");
   Thread t2=new Thread(p,"输出线程");
   t1.start();
   t2.start();
}
}
毕老师的程序分别建立两个类继承接口Runnable,分别实现线程单独的输入输出。而我用一个类继承Runnable,然后在里面判断输入输出线程所要执行的各自代码。但不知道问题出现在哪儿了

评分

参与人数 1技术分 +1 收起 理由
创出一片辉煌 + 1 记住同步的两个前提!

查看全部评分

11 个回复

倒序浏览
稍等一下哈!
回复 使用道具 举报
本帖最后由 马镱洵 于 2012-9-7 13:32 编辑

一切答案都在下面的代码,请仔细看代码中的注释:
  1. package heimabbs;

  2. class Ticket {

  3.         private String name;
  4.         public int count = 0;

  5.         public void set(String name) {
  6.                 this.name = name;
  7.         }

  8.         public String get() {
  9.                 return this.name;
  10.         }

  11. }

  12. class TicketRun implements Runnable {

  13.         private Ticket tc;
  14.         boolean flag = false;

  15.         TicketRun(Ticket tc) {
  16.                 this.tc = tc;
  17.         }

  18.         public void run() {
  19. // 判断字符串是否相同,当然是用equals()方法了.
  20.                 if (Thread.currentThread().getName().equals("输入线程")) {
  21.                         while (true) {
  22.                                 synchronized (tc) {
  23.                                         // 这里一定要将if改为while哦,要不然多个线程间很容易造成死锁.
  24.                                         // 我就不说为什么了,用文字会说很多的,老毕的视频会详细讲到的.
  25.                                         while (flag)
  26.                                                 try {
  27.                                                         // 锁的什么对象,就要用该对象来调用wait()方法.
  28.                                                         tc.wait();
  29.                                                 } catch (Exception e) {
  30.                                                         e.printStackTrace();
  31.                                                 }

  32.                                         tc.set("HeMingHui");
  33.                                         System.out.println(Thread.currentThread().getName()
  34.                                                         + tc.get() + tc.count++);
  35.                                         flag = true;

  36.                                         // 锁的什么对象,就要用该对象来调用notify()方法.
  37.                                         tc.notify();
  38.                                 }
  39.                         }
  40.                 } else
  41.                         while (true) {
  42.                                 synchronized (tc) {
  43.                                         // 这里一定要将if改为while哦,要不然多个线程间很容易造成死锁.
  44.                                         // 我就不说为什么了,用文字会说很多的,老毕的视频会详细讲到的.
  45.                                         while (!flag)
  46.                                                 try {
  47.                                                         // 锁的什么对象,就要用该对象来调用wait()方法.
  48.                                                         tc.wait();
  49.                                                 } catch (Exception e) {
  50.                                                         e.printStackTrace();
  51.                                                 }

  52.                                         System.out.println(Thread.currentThread().getName()
  53.                                                         + tc.get() + tc.count);
  54.                                         flag = false;

  55.                                         // 锁的什么对象,就要用该对象来调用notify()方法.
  56.                                         tc.notify();
  57.                                 }
  58.                         }
  59.         }

  60. }

  61. public class TicketDemo {

  62.         public static void main(String[] args) {
  63.                 Ticket tc = new Ticket();
  64.                 TicketRun p = new TicketRun(tc);
  65.                 Thread t1 = new Thread(p, "输入线程");
  66.                 Thread t2 = new Thread(p, "输出线程");
  67.                 t1.start();
  68.                 t2.start();
  69.         }

  70. }
复制代码
回复 使用道具 举报
本帖最后由 应广驰 于 2012-9-7 14:03 编辑

把this.notify();改成tc.notify();就好了, 要明确解开哪个锁,还有判断字符串要用equlas方法
回复 使用道具 举报
马镱洵 发表于 2012-9-7 13:31
一切答案都在下面的代码,请仔细看代码中的注释:

非常感谢你能帮我解答问题。但是上面的程序又出现了死锁,原因出现在什么地方了?
毕老师说当被操作的公共数据判断的时候需要加同步
但是线程中如果有操作的公共资源中有数据变化时是不是也要同步啊,
例如:打印变量x,System.out.println(x);x--;如果在某一时刻要打印的x的值是87,但是运行该数据的线程t1被运行该数据的线程t2抢走,并且改变了x值,那么等到转换t1的时候是不是打印改变之后的x值,那么在输出变化的x值时应该会重复吧
回复 使用道具 举报
何明辉 发表于 2012-9-7 17:28
非常感谢你能帮我解答问题。但是上面的程序又出现了死锁,原因出现在什么地方了?
毕老师说当被操作的公 ...

"但是上面的程序又出现了死锁,原因出现在什么地方了?"

不是死锁,而是死循环,是最外面那个while造成的.



"但是线程中如果有操作的公共资源中有数据变化时是不是也要同步啊"

我很肯定的回答,是.
回复 使用道具 举报
马镱洵 发表于 2012-9-7 17:54
"但是上面的程序又出现了死锁,原因出现在什么地方了?"

不是死锁,而是死循环,是最外面那个while造成的. ...

为什么不能实现交替打印了,只是输入一行数据之后程序就挂那儿了
回复 使用道具 举报
何明辉 发表于 2012-9-7 21:07
为什么不能实现交替打印了,只是输入一行数据之后程序就挂那儿了
  1. package heimabbs;

  2. class Ticket {

  3.         private String name;
  4.         public int count = 0;

  5.         public void set(String name) {
  6.                 this.name = name;
  7.         }

  8.         public String get() {
  9.                 return this.name;
  10.         }

  11. }

  12. class TicketRun implements Runnable {

  13.         private Ticket tc;
  14.         boolean flag = false;

  15.         TicketRun(Ticket tc) {
  16.                 this.tc = tc;
  17.         }

  18.         public void run() {
  19.                 // 判断字符串是否相同,当然是用equals()方法了.
  20.                 if (Thread.currentThread().getName().equals("输入线程")) {
  21.                         while (true) {
  22.                                 synchronized (tc) {
  23.                                         // 这里一定要将if改为while哦,要不然多个线程间很容易造成死锁.
  24.                                         // 我就不说为什么了,用文字会说很多的,老毕的视频会详细讲到的.
  25.                                         while (flag)
  26.                                                 try {
  27.                                                         // 锁的什么对象,就要用该对象来调用wait()方法.
  28.                                                         tc.wait();
  29.                                                 } catch (Exception e) {
  30.                                                         e.printStackTrace();
  31.                                                 }

  32.                                         tc.set("HeMingHui");
  33.                                         System.out.println(Thread.currentThread().getName()
  34.                                                         + tc.get() + tc.count++);
  35.                                         flag = true;

  36.                                         // 锁的什么对象,就要用该对象来调用notify()方法.
  37.                                         tc.notify();
  38.                                 }
  39.                         }
  40.                 } else
  41.                         while (true) {
  42.                                 synchronized (tc) {
  43.                                         // 这里一定要将if改为while哦,要不然多个线程间很容易造成死锁.
  44.                                         // 我就不说为什么了,用文字会说很多的,老毕的视频会详细讲到的.
  45.                                         while (!flag)
  46.                                                 try {
  47.                                                         // 锁的什么对象,就要用该对象来调用wait()方法.
  48.                                                         tc.wait();
  49.                                                 } catch (Exception e) {
  50.                                                         e.printStackTrace();
  51.                                                 }

  52.                                         System.out.println(Thread.currentThread().getName()
  53.                                                         + tc.get() + tc.count);
  54.                                         flag = false;

  55.                                         // 锁的什么对象,就要用该对象来调用notify()方法.
  56.                                         tc.notify();
  57.                                 }
  58.                         }
  59.         }

  60. }

  61. public class TicketDemo {

  62.         public static void main(String[] args) {
  63.                 Ticket tc = new Ticket();
  64.                 TicketRun p = new TicketRun(tc);
  65.                 Thread t1 = new Thread(p, "输入线程");
  66.                 Thread t2 = new Thread(p, "输出线程");
  67.                 t1.start();
  68.                 t2.start();
  69.         }

  70. }
复制代码
你看,没问题啊,我给你的代码不存在你说的死锁问题.
回复 使用道具 举报
何明辉 发表于 2012-9-7 21:07
为什么不能实现交替打印了,只是输入一行数据之后程序就挂那儿了

你好好把你的代码和我给你的代码对照一下,你一定有错误代码的地方.
回复 使用道具 举报
马镱洵 发表于 2012-9-7 23:29
你看,没问题啊,我给你的代码不存在你说的死锁问题.

应该是死循环,我在dos命令行下运行的数据的,成许总是输入第一行后就停滞不动了,没有实现交替打印的效果。

RDWC_)UT}(`{WXW[BPNXDWP.jpg (5.72 KB, 下载次数: 34)

RDWC_)UT}(`{WXW[BPNXDWP.jpg
回复 使用道具 举报
何明辉 发表于 2012-9-7 23:39
应该是死循环,我在dos命令行下运行的数据的,成许总是输入第一行后就停滞不动了,没有实现交替打印的效 ...

你看吧,交替打印的啊.

QQ截图20120907235749.jpg (77.25 KB, 下载次数: 27)

QQ截图20120907235749.jpg
回复 使用道具 举报
何明辉 发表于 2012-9-7 23:39
应该是死循环,我在dos命令行下运行的数据的,成许总是输入第一行后就停滞不动了,没有实现交替打印的效 ...

你把代码修改后要重新编译的哦.
干脆你把代码发上来看看.
回复 使用道具 举报
您需要登录后才可以回帖 登录 | 加入黑马