我看这个关于 wait,notify,sleep,join和线程同步问题 的贴子
http://blog.csdn.net/treeroot/archive/2004/11/10/175508.aspx里边有个例题,模拟了俩个人分别用洗手间的情况,其中:
第一个先刷牙,刷完后,第二个人刷,然后第一个人上厕所,完后再第一个人
就是洗手间(包括厕所功能不能同时用)我改一下,把洗手间划分为,厕所和洗漱间,一分为二,就是:
第一人刷牙的同时,第二个人上厕所,然后再交换,这里刷牙和上厕所时间是不同的但是怎么就没有第二个过程,就是第一人上厕所,第2个人刷牙
请各位大侠帮我看看到底怎么回事?非常感谢━━我修改后代码━━━━━━━━━━━━━━━━━━━━━━━━━━
class Syn
{
        public static void main(String[] args) throws Exception
        {
            TwoPeople.ONE.start();
            TwoPeople.TWO.start();
        }
} class TwoPeople extends Thread{
    private int i=0;
    static Thread ONE=new TwoPeople(1);
    static Thread TWO=new TwoPeople(2);    static Object washroom=new Object();  
    static Object Toilet=new Toilet();     //我加的 厕所 对象
    private TwoPeople(int i){this.i=i;}
    public void run(){
//头:这是我修改的代码
       try{
     if(i==1){
        synchronized(washroom){
         brush();
         ONE.wait();
         TWO.notify();
         release();
         }
        }else {synchronized(toilet){
         release();
         TWO.wait();
         ONE.notify();
         brush();
            }
        }}catch(Exception e){}
//尾:这是我修改的代码    private void brush() {
            System.out.println("People "+i+" is brushing !");
             try{Thread.sleep(2000);}catch(InterruptedException e){e.printStackTrace();}
            //延迟两秒看效果
            System.out.println("People "+i+" has burshed !");
    }
    private void release(){
            System.out.println("People "+i+" is releasing !");
            try{Thread.sleep(2000);}catch(InterruptedException e){e.printStackTrace();}
            //延迟两秒看效果
            System.out.println("People "+i+" has released !");
    }
}━━━━━━━━━━━━━━━━━━━━━━━━━━━━
━━以下是原帖中的run方法━━━━━━━━━━━━━━━
/*
        synchronized(washroom){
            try{
                if(i==1){
                    brush(); //1 
                  washroom.wait(); //2
                    release(); //6   
                    washroom.notify(); //7
                }
            else{
                    brush(); //3
                    washroom.notify(); //4
                    washroom.wait(); //5
                    release(); //8
            }
            }catch(InterruptedException e){e.printStackTrace();}
        }
    }*/

解决方案 »

  1.   

    谢谢大侠!这个问题郁闷我二天了!
    ━━━━━━━━━━━━━━━━━━━━━━━━━━━━
    代码不用全看,关键的就是run方法里的内容我想实现的就是,
    俩个人俩个线程,一个人刷牙,另个一个人同时上厕所,
    牙刷完的人等上厕所,第二个人上完,第一个人就上,同时,第二个人开始刷牙
    (当然刷牙所时间可能比上厕所时间长,反正就是谁先结束就先进入等待状态)听起来很简单,可是实现起来怎么那么困难呢?我昨天睡觉都在想,郁闷到吐血了我用整理以下我的run方法,思路应该很清晰吧
    ━━━━━━━━━━━━━━━━━━━━━━━━━━━━
    if(i==1){
            synchronized(washroom) {
        try{
    brush();
                      washroom.wait();
             toilet.notify();
                      release();
             }catch(InterruptedException e){e.printStackTrace();}
            }
           
            }else {
         synchronized(toilet){
          try{
          release();
          toilet.wait();
            washroom.notify();
                      brush();
            }catch(Exception e){e.printStackTrace();}
    }
      

  2.   

    可以运行的代码。比较一下就可以得出答案。
    class Syn
    {
    public static void main(String[] args) throws Exception
    {
    TwoPeople.ONE.start();
    TwoPeople.TWO.start();
    }
    }class TwoPeople extends Thread
    {
    private int i = 0;
    static Thread ONE = new TwoPeople(1);
    static Thread TWO = new TwoPeople(2); static Object washroom = new Object();
    static Object toilet = new Object();  private TwoPeople(int i)
    {
    this.i = i;
    } public void run()
    {
    try
    {
    if (i == 1)
    {
    brush();
    release();
    }
    else
    {
    release();
    brush();
    } }
    catch (Exception e)
    {
    e.printStackTrace();
    }
    } private void brush()
    {
    synchronized (washroom)
    {
    System.out.println("People " + i + " is brushing !");
    try
    {
    Thread.sleep(1000);
    }
    catch (InterruptedException e)
    {
    e.printStackTrace();
    }

    System.out.println("People " + i + " has burshed !");

    washroom.notify();
    }
    } private void release()
    {
    synchronized (toilet)
    {
    System.out.println("People " + i + " is releasing !");
    try
    {
    Thread.sleep(2000);
    }
    catch (InterruptedException e)
    {
    e.printStackTrace();
    }
             System.out.println("People " + i + " has released !");

    toilet.notify();
    }
    }
    }
      

  3.   

    其实不用显式地notify(),系统在synchronized语句块之后会自动调用。
      

  4.   

    class CSDN13 {
    public static void main(String[] args) throws Exception {
    TwoPeople.ONE.start();
    TwoPeople.TWO.start();
    }
    }class Toilet {}class TwoPeople extends Thread {
    private int i = 0; static Thread ONE = new TwoPeople(1); static Thread TWO = new TwoPeople(2); static Object washroom = new Object(); static Object toilet = new Toilet(); // 我加的 厕所 对象 private TwoPeople(int i) {
    this.i = i;
    } public void run() {
    // 头:这是我修改的代码
    try {
    if (i == 1) {
    synchronized (washroom) {  //如果没人刷牙,就开始使用washroom
    brush(); //刷牙
    washroom.notify();//刷完牙让位,通知其它等待刷牙的人用
    //TWO.notify();

    }
    synchronized (toilet) { //等待la'shi
    release();   //lashi
    toilet.notify();  //拉完了,通知其它人拉
    }

    else {
    synchronized (toilet) {  //如果没人拉,就开始拉,如果有人,等待
    release();//开始……
    toilet.notify();  //完了,好爽,通知其它等待的人 }
    synchronized (washroom) {  //如果没人刷牙,就开始使用washroom,如果有人就等待
    brush();
    washroom.notify();//刷完牙让位,通知其它等待刷牙的人用

    }
    }
    } catch (Exception e) {
    }
    } // 尾:这是我修改的代码 private void brush() {
    System.out.println("People " + i + " is brushing !");
    try {
    Thread.sleep(200);
    } catch (InterruptedException e) {
    e.printStackTrace();
    }
    // 延迟两秒看效果
    System.out.println("People " + i + " has burshed !");
    } private void release() {
    System.out.println("People " + i + " is releasing !");
    try {
    Thread.sleep(200);
    } catch (InterruptedException e) {
    e.printStackTrace();
    }
    // 延迟两秒看效果
    System.out.println("People " + i + " has released !");
    }
    }
      

  5.   

    if(i==1){
    synchronized(washroom){
    brush();
    ONE.wait();
    TWO.notify();
    release();
    }
    }else {synchronized(toilet){
    release();
    TWO.wait();
    ONE.notify();
    brush();
    }楼主这部分代码有问题,主要是理解上的错误。既然对toilet对象上锁,就不用ONE,TWO来唤醒和释放
      

  6.   

    额写个N个人排队上厕所,刷牙滴!
    呵呵
    package com.ttdev.tcpmonitor;import java.util.ArrayList;
    import java.util.List;
    import java.util.Random;
    public class Syn
    {
            public static void main(String[] args) throws Exception
            {
             WashRoom room = new WashRoom();
             Toilet toilet = new Toilet();
             People p1 = new People(room,toilet);
             People p2 = new People(room,toilet);
             People p3 = new People(room,toilet);
             p1.start();
             p2.start();
             p3.start();
            }
    } class People extends Thread{
        private List   locationList  = new ArrayList();
        private List   queue        = new ArrayList();
        public void addLocation(Object location)
        {
         if(!locationList.contains(location))
         {
         locationList.add(location);
         }
        }
         
        public People(WashRoom room,Toilet toilet)
        {
         locationList.add(room);
         locationList.add(toilet);
        }
        private Location nextLocation()
        {
         int size = queue.size();
         if(size == 0)
         {
         //重走!
         queue = new ArrayList();
         queue.addAll(locationList);
         size = queue.size();
         }
         Random  r = new Random();
     
         int index = r.nextInt(size);
         Location location = (Location)queue.get(index);
         queue.remove(index);//
         return location;
        
        }
        
        public void run()
        {
         while(true)
         {
          Location location = nextLocation();
          synchronized(location)
          {
          location.toDo();
          location.release();
          }
         }
         }
    }
        
       abstract class Location
       {
       protected boolean inUse;
       public void  toDo(){};
       void  release(){};
       }   class  Toilet extends Location
       {
       
      public synchronized void toDo()
      {
     while(inUse)
       {
       try {
    wait();
    } catch (InterruptedException e) {
    // TODO Auto-generated catch block
    e.printStackTrace();
    }
       }
    System.out.println(Thread.currentThread().getName()+" is  in the  toilet! ");
      
      }
      public synchronized  void release()
      {
      inUse =false;
      System.out.println(Thread.currentThread().getName()+" release the Toilet !");
      notifyAll();
      }
       }
        class WashRoom  extends Location
        {
         public synchronized  void toDo()
         {
         while(inUse)
         {
         try {
    wait();
    } catch (InterruptedException e) {
    // TODO Auto-generated catch block
    e.printStackTrace();
    }
         }
         System.out.println(Thread.currentThread().getName()+" is  in the  WashRoom! ");
        
        
         }
            public synchronized  void release()
           {
               inUse =false;
               System.out.println(Thread.currentThread().getName()+" release the  WashRoom ");
           notifyAll();
           }
        }
      

  7.   

    对不起:
         System.out.println(Thread.currentThread().getName()+" is  in the  WashRoom! ");之前要加一行:inUse=true;
    还有 System.out.println(Thread.currentThread().getName()+" is  in the  toilet! ");之前要加一行:inUse=true;
      

  8.   

    小弟看了半天可算有个大概的理解了。
    Rayuu  的代码,没有用到wait方法,简单好多,以无刀胜有刀!强!
    ‘其实不用显式地notify(),系统在synchronized语句块之后会自动调用。’
    这句话蛮有用的,注释掉notify,结果都一样哈。
    fishyqd 代码通俗易懂,还加了注释,谢谢了
    我原来可能就是要这个效果吧,我水平差,一直没写成。
    Octer 一看就是世外高人呀!我俩个人都弄得焦头烂额的
    代码有些地方我还得好好理解,arraylist这个类我不太熟悉原理我这样理解的:
    人是个类,要去的地方是写个对象(洗漱和厕所),
    要去的地方有个顺序,先去厕所还是先去洗漱,是这个意思吧?
    随机生成的,这个地方,没太看明白
    然后运行了,要去的地方加个锁,动作也加了个锁吧?
    判断,在不在用?执行动作
    最后释放锁
    循环是在重走那加的吧?
    运行了一下,发现,初始状态是有人已经上厕所中……
    有发现,有时某人重复上厕所好多次,拉肚子了吧代码我还得理解一下再次感谢所有热心的大侠们!谢谢ps.分数怎么给,小弟分不多,平分不了哇
    编写一个代码,随机一下三个数和为20 的,然后依次给吧
    我这个代码太不优化了,丢人呀结果:
    6 7 7
    ━━随机分数代码━━━━━━━━━━━━━━━━━━━━━━━━
    //随机6-8之间的三个数,使其和为20
    import java.util.Random;
    public class Syn{
    public static void main (String[] args){
    Random r = new Random();
    int x,y;
    while (true){
    x=r.nextInt(8);
    y=r.nextInt(8);
    if (x<6 && y<6){
    x=r.nextInt(8);
    y=r.nextInt(8);
    //System.out.println (x+"\t"+y);
    }else if ( ((20-x-y)>=6) && ((20-x-y)<=8) ){
    System.out.println (x+" "+y+" "+(20-x-y));
    break;

    }
    }
    }
      

  9.   

    呵呵,其实同步会降低代码的运行效率的,通过 notity wait 或者notifyAll 做到间通信,而同步则依赖于同步监试器,当有线程进入该同步代码块或者同步方法,其他线程就无法进入该对象的同步方法。wait是在不满足某些条件下,线程处于阻塞状态,等待notify或者notifyAll去唤醒
    如果代码改成这样:
    package com.ttdev.tcpmonitor;import java.util.ArrayList;
    import java.util.List;
    import java.util.Random;
    public class Syn
    {
            public static void main(String[] args) throws Exception
            {
             WashRoom room = new WashRoom();
             Toilet toilet = new Toilet();
             People p1 = new People(room,toilet);
             People p2 = new People(room,toilet);
             People p3 = new People(room,toilet);
             p1.start();
             p2.start();
             p3.start();
            }
    } class People extends Thread{
    private List   locationList  = new ArrayList();
        private List   queue        = new ArrayList();
        public synchronized void  addLocation(Object location)
        {
         if(!locationList.contains(location))
         {
         locationList.add(location);
         }
        }
        public People(WashRoom room,Toilet toilet)
        {
         addLocation(room);
         addLocation(toilet);
        }
        private Location nextLocation()
        {
         int size = queue.size();
         if(size == 0)
         {
         //拉肚子了,同时该人有洁癖,继续上厕所,洗漱!
         queue = new ArrayList();
         queue.addAll(locationList);
         size = queue.size();
         }
         Location location = (Location)queue.get(0);
         queue.remove(0);
         return location;
        
        }
        
        public void run()
        {
         while(true)
         {
          Location location = nextLocation();
          //synchronized(location) // discard this line for testing the multi-threads communication   
          {
          location.toDo();
          //location.release();
          }
         }
         }
    }
    abstract class Location
       {
       protected boolean inUse;
       public void  toDo(){};
       void  release(){};
       }   class  Toilet extends Location
       {
       
      public synchronized void toDo()
      {
     while(inUse)
       {
       try {
    wait();
    } catch (InterruptedException e) {
    // TODO Auto-generated catch block
    e.printStackTrace();
    }
       }
    inUse =true;
    System.out.println(Thread.currentThread().getName()+" is  in the  toilet! ");
    release();
      
      }
      public   void release()
      {
      inUse =false;
      System.out.println(Thread.currentThread().getName()+" release the Toilet !");
      notifyAll();
      }
      public String toString()
      {
      return "Toilet:"+this.hashCode();
      }
       }
        class WashRoom  extends Location
        {
         public synchronized  void toDo()
         {
         while(inUse)
         {
         try {
    wait();
    } catch (InterruptedException e) {
    // TODO Auto-generated catch block
    e.printStackTrace();
    }
         }
         inUse =true;
         System.out.println(Thread.currentThread().getName()+" is  in the  WashRoom! ");
         release();
         }
            public synchronized  void release()
           {
               inUse =false;
               System.out.println(Thread.currentThread().getName()+" release the  WashRoom ");
           notifyAll();
           }
            public String toString()
            {
              return "WashRoom:"+this.hashCode();
            }
        }