title: wait() or notifyAll() creating infinite loop
body: <p>I have a program which simulates an Airport which is based on the code found here: <a href="http://www.javapractices.com/topic/TopicAction.do?Id=51" rel="nofollow">http://www.javapractices.com/topic/TopicAction.do?Id=51</a></p>
  
  <p>Which has three classes: Airport, Airplane and AirportSimulator (in my case) and uses threads to synchronise actions.</p>
  
  <p>The problem I'm having is that when the airplane is waiting for runway space for landing, the notifyAll() function doesn't seem to be working, and as such the airplane stays in an infinite loop of "waiting" for space.</p>
  
  <p>I <em>think</em> the problem lies with either the wait() being infinite due to not being interrupted, or the notifyAll() not working and notifying the threads (airplanes) which are waiting on them.</p>
  
  <p>Any help is appreciated.</p>
  
  <p>EDIT: Here are the classes.</p>
  
  <p>Airplane.java</p>
  
  <pre><code>public class Airplane implements Runnable
  {
      public Airplane(Airport anAirport, String FlightID)
      {
          fAirport = anAirport;
          aFlightID = FlightID;
      }
  
      @Override
      public void run()
      {
          takeOff();
          fly();
          land();
      }
  
      //Private
      private Airport fAirport;
      private String aFlightID;
  
      private void takeOff()
      {
          synchronized(fAirport)
          {
              while(!fAirport.hasAvailableRunway())
              {
                  System.out.println(aFlightID + ": waiting for runway space");
                  try
                  {
                      fAirport.wait();
                  }
                  catch(InterruptedException ex)
                  {
                      System.err.println(ex);
                      Thread.currentThread().interrupt();
                  }
              }
              System.out.println(aFlightID + ": departing now...");
          }
      }
  
      private void fly()
      {
          System.out.println(aFlightID + ": now flying...");
          try
          {
              //wait for 10 seconds
              Thread.sleep(10000);
          }
          catch(InterruptedException ex)
          {
              System.err.println(ex);
              Thread.currentThread().interrupt();
          }
      }
  
      private void land()
      {
          synchronized(fAirport)
          {
              while(!fAirport.hasAvailableRunway())
              {
                  System.out.println(aFlightID + ": waiting for runway space");
                  try
                  {
                      fAirport.wait();
                  }
                  catch(InterruptedException ex)
                  {
                      System.err.println(ex);
                      Thread.currentThread().interrupt();
                  }
              }
          }
      }
  }
  </code></pre>
  
  <p>Airport.java</p>
  
  <pre><code>public class Airport implements Runnable
  {
  
      public Airport(String aName)
      {
          super();
          fName = aName;
      }
  
      public synchronized boolean hasAvailableRunway()
      {
          return fHasAvailableRunway;
      }
  
      @Override
      public void run()
      {
          System.out.println("Running: " + fName + " Airport.");
          while(true)
          {
              try
              {
                  synchronized(this)
                  {
                      //Toggle runway state between available and unavailable
                      fHasAvailableRunway = !fHasAvailableRunway;
                      System.out.println(fName + " Has Available Runway: " + fHasAvailableRunway);
                      //Notify waiters of the state change
                      this.notifyAll();
                  }
                  Thread.sleep(2000); //Pause for a couple of seconds
              }
              catch(InterruptedException ex)
              {
                  System.err.println(ex);
                  Thread.currentThread().interrupt();
              }
          }
      }
  
      //Private
      private boolean fHasAvailableRunway = true;
      private String fName;
  
  }
  </code></pre>
  
  <p>And finally, AirportSimulator.java</p>
  
  <pre><code>public class AirportSimulator 
  {
      public static void main(String[] args)
      {
          System.out.println("Running Airport Simulation");
  
          //Create an airport and start running
          Airport leedsBradfordAirport = new Airport("Leeds &amp; Bradford International");
          Thread airport = new Thread(leedsBradfordAirport);
          airport.start();
  
          //Create a plane and start running
          Thread airplaneOne = new Thread(new Airplane(leedsBradfordAirport, "Flight 2112"));
          //Thread airForceTwo = new Thread(new Airplane(leedsBradfordAirport, "Flight 1986"));
          airplaneOne.start();
          //airForceTwo.start();
  
          System.out.println("Terminating original thread");
      }
  }
  </code></pre>