为什么IllegalMonitorStateException?

时间:2017-04-15 17:21:14

标签: java multithreading

我正在尝试使用三个线程进行交替打印。 第一个线程应该打印一个数字,然后第二个线程打印第二个数字,然后第三个线程我尝试使用共享静态整数实现它,但我的代码显示IllegalMonitorStateException。任何人都可以检查一下并告诉我的错误吗?

class ThreadRevisit extends Thread
{
static Integer number;
int num;
ThreadRevisit(String name,Integer number,int num)
{
  super(name);
  this.number=number;
  this.num=num;
}

 public void run()
{
  int n= number;
  do
  {
  synchronized(ThreadRevisit.number)
       {
           if(n>100)
           {
           number.notifyAll();
           break;
           }
           if (n%3==num)
           {
              System.out.println(Thread.currentThread().getName()+" "+num);
              number=number+1;
           }
            number.notifyAll();
            try
            {
             number.wait();
            }catch(Exception e)
            {

            }
       }
     }
   while(true);

    } 
}
class T1
{
public static void main(String[] ar) 
 {
 Integer inn=new Integer(0);
 ThreadRevisit.number=inn;
 ThreadRevisit t1=new ThreadRevisit("one",inn,0);
 ThreadRevisit t2=new ThreadRevisit("two",inn,1);
 ThreadRevisit t3=new ThreadRevisit("three",inn,2);

 t1.start();
 t2.start();
 t3.start();
 }

3 个答案:

答案 0 :(得分:0)

第27行

number=number+1;

您有效地将对象编号更改为具有增加值的新编号。所以新的没有附加监视器,这导致错误。

答案 1 :(得分:0)

我在你的代码中看到了一个问题(实际上与Marcin Krasowski提到的相同):你重新分配Integer变量。这意味着还有另一个实例正在运行,而wait / notify将在错误的Integer对象上发生。

我从来都不喜欢wait / notify方法,你也可以使用观察者模式,其中第二个线程观察第一个线程写入其输出,第三个线程观察第二个线程相同。

答案 2 :(得分:0)

IllegalMonitorStateException

  

抛出此异常表示某个线程试图在对象的监视器上等待,或者在没有指定监视器的情况下通知在对象监视器上等待的其他线程。

正如Marcin Krasowski所说,这个数字已经改变了。 您使用

锁定了号码
synchronized(ThreadRevisit.number)

稍后您更改了number

当您呼叫notifyAll()时,您没有锁定最初获得锁定的号码对象。

您应该避免更改获取锁定的对象。