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

 找回密码
 加入黑马

QQ登录

只需一步,快速开始

© 梁清平 中级黑马   /  2012-5-26 10:00  /  1511 人查看  /  4 人回复  /   0 人收藏 转载请遵从CC协议 禁止商业使用本文

//练习线程间的通迅
//资源类
class Res
{
String name;
String sex;
boolean f = false;
}
class Input implements Runnable
{
private Res s;
Input(Res s)
{
  this.s = s;
}
public void run()
{
  int i = 0;
  while(true)
  {
   synchronized(s)
   {
    if(s.f)
     try{s.wait();}catch(Exception e){}
    if(i==0)
    {
     s.name = "lily";
     s.sex = "girl";
    }
    else
    {
     s.name = "小菊";
     s.sex = "女";
    }
    i=(i+1)%2;
    s.f = true;
    try{s.notify();}catch(Exception e){}   
   }   
  }
}
}
class Output implements Runnable
{
private Res s;
Output(Res s)
{
  this.s = s;
}
public void run()
{
  while(true)
  {
   synchronized(s)
   {
    if(!s.f)
     try{s.wait();}catch(Exception e){}
    else
     System.out.println(s.name+"..."+s.sex);
    s.f = false;
    try{s.notify();}catch(Exception e){}   
   }
  }
}  
}
public class WaitNotifyDemo
{
public static void main(String[] args)
{
  Res s = new Res();
  new Thread(new Input(s)).start();
  new Thread(new Output(s)).start();
}
}
这我还程序在运行时为什么会出现多个中文或者多个英文的输出啊?

点评

这代码排版 会把人看晕的 ~~  发表于 2012-5-26 14:10

4 个回复

正序浏览
本帖最后由 谢述华 于 2012-5-28 18:52 编辑

把二楼的代码用图表示下,这样更清晰,方便大家讨论分析。
另外,这段代码很好的示范了synchronized 和sleep/notify的用法,却因为严格的执行顺序而缺少了实战型。可以轻易被如下代码代替...
  1. while(true){
  2. s.name = "lily";
  3. s.sex = "girl";
  4. System.out.println(s.name+"......."+s.sex);
  5. s.name = "小菊";
  6. s.sex = "女";
  7. System.out.println(s.name+"......."+s.sex);
  8. }
复制代码

运行图解.png (5.77 KB, 下载次数: 35)

运行图解.png
回复 使用道具 举报
打印结果

未命名.jpg (19.41 KB, 下载次数: 35)

未命名.jpg
回复 使用道具 举报
本帖最后由 李斌 于 2012-5-26 12:43 编辑


class Res
{
String name;
String sex;
boolean f = false;
}
class Input implements Runnable
{
private Res s;
Input(Res s)
{
  this.s = s;
}
public void run()
{
  int i = 0;
  while(true)
  {
   synchronized(s)
   {

    while(s.f)-------------循环判断标记!!!
     try{s.wait();}catch(Exception e){}
    if(i==0)
    {
     s.name = "lily";
     s.sex = "girl";
    }
    else
    {
     s.name = "小菊";
     s.sex = "女";
    }
    i=(i+1)%2;
    s.f = true;
    try{s.notifyAll();}catch(Exception e){}   
   }   
  }
}
}
class Output implements Runnable
{
private Res s;
Output(Res s)
{
  this.s = s;
}
public void run()
{
  while(true)
  {
   synchronized(s)
   {
    while(!s.f)------------循环判断标记哦~~
     try{s.wait();}catch(Exception e){}

    System.out.println(s.name+"..."+s.sex);
    s.f = false;
    try{s.notifyAll();}catch(Exception e){}   
   }
  }
}  
}
public class WaitNotifyDemo
{
public static void main(String[] args)
{
  Res s = new Res();
  new Thread(new Input(s)).start();
  new Thread(new Output(s)).start();
}
}

1.哥们你没有循环判断标记 当然就会出现数据错乱啦 ~~~~
2.没有用notifyAll 唤醒对方线程;
当然就会出现数据错乱啦 ~~~~


评分

参与人数 1技术分 +1 收起 理由
贠(yun)靖 + 1

查看全部评分

回复 使用道具 举报
本帖最后由 麦田里的守望者 于 2012-5-26 12:22 编辑

你那个等待唤醒机制定义有点问题,下面我修改了一下你可以看看就能够解决你上面的问题,能间隔输出
class Res
{
        String name;
        String sex;
        boolean flag = false ;
}


class Input implements Runnable
{
        private Res s;
         Input(Res s)
        {
                this.s = s;
        }
        public void run()
        {
                int x = 0;
                while(true)
                {
                        synchronized(s)
                        {

                                if(s.flag)
                                        try{s.wait();}catch(Exception e){}
                                if(x==0)
                                {
                                        s.name = "lily";
                                     s.sex = "girl";
                                }
                                else
                                {
                                           s.name = "小菊";
                                             s.sex = "女";
                                
                                }
                                s.flag = true;
                                s.notify();
                        }
                        x=(x+1)%2;
                }
        }
}


class Output implements Runnable
{
        private Res s ;
        Output(Res s)
        {
                this.s = s;
        }
        public void run()
        {
                while(true)
                {
                        synchronized(s)
                        {
                                if(!s.flag)
                                        try{s.wait();}catch(Exception e){}
                                System.out.println(s.name+"......."+s.sex);
                                s.flag = false;
                                s.notify();//唤醒。唤醒等待的线程。
                        }
                }
        }
}


class ResourceDemo
{
        public static void main(String[] args)
        {
                Res s = new Res();

                 new Thread(new Input(s)).start();
                 new Thread(new Output(s)).start();   
       }
}

评分

参与人数 1技术分 +1 收起 理由
贠(yun)靖 + 1

查看全部评分

回复 使用道具 举报
您需要登录后才可以回帖 登录 | 加入黑马