通知线程时出现IllegalMonitorStateException

时间:2013-03-27 11:50:20

标签: java multithreading

我有一个模拟盖茨船的程序。他们在线程中运行。我们的想法是让他们在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" 

现在有人在继续吗?

3 个答案:

答案 0 :(得分:1)

您只能在wait个区块内拨打notify/notifyAllsynchronized

答案 1 :(得分:0)

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

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

这是许多其他questions的主题。

答案 2 :(得分:0)

 t.notify();

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

此外,您可以查看CountDownLatch,它完全符合您的目标。