wait()或notifyAll()创建无限循环

时间:2014-03-26 16:34:55

标签: java multithreading

我有一个模拟机场的程序,该程序基于此处的代码:http://www.javapractices.com/topic/TopicAction.do?Id=51

其中有三个类:Airport,Airplane和AirportSimulator(在我的情况下)并使用线程来同步动作。

我遇到的问题是,当飞机正在等待跑道空间着陆时,notifyAll()功能似乎不起作用,因此飞机停留在“等待”的无限循环中空间。

认为问题在于wait()由于没有被中断而无限,或者notifyAll()没有工作,并通知正在等待它们的线程(飞机)。 / p>

感谢任何帮助。

编辑:这是课程。

Airplane.java

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();
                }
            }
        }
    }
}

Airport.java

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;

}

最后,AirportSimulator.java

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 & 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");
    }
}

1 个答案:

答案 0 :(得分:1)

当我运行程序时,Airplane线程不会挂起:它调用takeOff(),fly()和land()。之后它终止......

...没有打印任何消息。

每次我运行它时,在它调用land()的确切时刻,跑道都可用,因此它永远不会进入while()循环,它从不调用wait()。它只是回归,这就是故事的结束。


几点意见:

您的程序不会试图让多架飞机同时使用“跑道”。我加入了恐慌报价,因为你的模型中确实没有跑道。只有一个布尔标志,只要它是真的,那么每架想要起飞或降落的飞机都可以这样做。

您的程序排序处理InterruptedException,而排序则不处理。语言强迫你编写处理程序,并且在每个处理程序中,你仔细地重置了被中断的标志,但之后没有任何东西测试过标志。在大多数实际程序中,中断意味着“优雅地关闭”。在这种情况下,您希望在每个循环中测试isInterrupted(),并清理并退出,如果它是真的。

如果你不想解决所有麻烦,那么你也可以写下:

} catch (InterruptedException ex) {
    throw new RuntimeException(ex);
}