0

我有一个模拟船门的程序。它们在线程中运行。这个想法是让他们在 run 方法中的随机时刻运行和暂停,以模拟人员经过。这是由所有线程完成的,同时主线程正在等待通知并检查船是否已满,当线程通知他们添加了一个通过大门的人时,主线程再次检查船是否已满。该程序分为三个类:

计数器:

    public class Counter {
        private int currentValue[];
        private int maxValue;

        public Counter(int[] nrOfPeople, int max) {
            currentValue = nrOfPeople;
            currentValue[0] = 0;
            maxValue = max; 
        }

        public synchronized void addPersons(int nr_p) {
            currentValue[0] += nr_p;
        }

        public synchronized int getValue() {
            return currentValue[0];
        }

        public synchronized boolean isFull() {
            if(currentValue[0] < maxValue)
                return false;
            return true;
        }
    }

门类:

    public abstract class Gate implements Runnable {
        int nrOfPassengers;
        int gatenr;
        int gatesize;
        Counter c;
        private Thread t;
        private Random r;
        private boolean blocked; /* suspends people from passing */

        public Gate(Counter c, int nr) {
            this.c = c;
            gatenr = nr;
            this.open();
            r = new Random();
            t = new Thread(this);
            t.start();
        }

        public void setGatesize(int size) {
            gatesize = size;
        }

        public void close() {
            blocked = true;
        }

        public void open() {
            blocked = false;
        }

        public int getNoOfPassangers() {
            return nrOfPassengers;
        }

        public int getId() {
            return gatenr;
        }

        @Override
        public void run() {
            while(!blocked) {
                int waitTime = (r.nextInt(5) + 1) * 1000; /* between 1-5 seconds */
                System.out.println("Person-Gate " + gatenr + ": adding one to " + c.getValue());
                try {
                    /* bigger throughput => amount can vary */
                    if(gatesize > 1) {
                        int persons = r.nextInt(gatesize)+1;
                        c.addPersons(persons);
                        nrOfPassengers += persons;
                    } else {
                        c.addPersons(1);
                        nrOfPassengers++;
                    }
                    Thread.sleep(waitTime);
                } catch (InterruptedException e) {
                    System.out.println("Person-Gate " + gatenr + ": was interrupted adding person");
                    e.printStackTrace();
                }
                System.out.println("Person-Gate " + gatenr + ": added one to " + c.getValue());
                t.notify();
            }
        }

        public void join() {
            try {
                t.join();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }

还有一个运行主要方法的模拟器:

    /*
     * This class simulates cars and persons- entering a ferry.
     */
    public class Simulator {

        public static final int MAX = 30;

        public static void main(String[] args) {
            int nrOfPeople[] = new int[1]; /* array of size one for keeping count */
            ArrayList<Gate> gates = new ArrayList<Gate>();
            Counter counter = new Counter(nrOfPeople, MAX);
            Thread mainThread = Thread.currentThread();

            /* adding 3 person-gates */
            for(int i=1; i<4; i++) {
                gates.add(new PersonGate(counter, i));
            }

            /* let all gates work as long as passengers is under MAX */
            while(!counter.isFull()) { 
                try {
                    mainThread.wait();
                } catch (InterruptedException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                }
            }
            System.out.println("Announcement: Ship is full!");

            /* wait for child threads to finish */
            for(Gate g: gates) {
                g.close();
                try {
                    g.join();
                } catch (Exception e) { /* InterruptedException */
                    e.printStackTrace();
                }
                System.out.println(g.getNoOfPassangers() + " passed through gate nr " + g.getId());
                System.out.println(counter.getValue() + " has passed in total");
            }

        }
    }

我收到一个错误

Person-Gate 1: adding one to 0
Person-Gate 2: adding one to 1
Person-Gate 3: adding one to 2
Exception in thread "main" java.lang.IllegalMonitorStateException
at java.lang.Object.wait(Native Method)
at java.lang.Object.wait(Object.java:485)
at Simulator.main(Simulator.java:24)
Person-Gate 3: added one to 3Exception in thread "Thread-3" 

有人现在发生了什么事吗?

4

3 回答 3

1

您只能在块内调用wait和。notify/notifyAllsynchronized

于 2013-05-15T13:52:00.390 回答
0

您必须拥有调用 wait 或 notify 的对象的监视器。意思是,你必须在一个同步块中,比如

synchronized( objectUsedAsSynchronizer) {
    while ( mustStillWait) {
        objectUsedAsSynchronizer.wait();
    }
}

这是许多其他问题的主题。

于 2013-03-27T11:55:59.693 回答
0
 t.notify();

您正在通知错误的监视器。当您不使用synchronize节包装监视器对象时,会发生此异常。但是,您用于通知和等待方法的对象是不同的。创建new Object()监视器并将其传递给 Gate 的构造函数。

您也可以看一下CountDownLatch,它完全符合您的要求。

于 2013-03-27T12:00:16.910 回答