为什么这个方法会抛出IllegalMonitorStateException?

时间:2010-05-06 04:34:55

标签: java multithreading concurrency

  public static synchronized void main(String[] args) throws InterruptedException {
    Thread t = new Thread();
    t.start();
    System.out.print("X");
    t.wait(10000);
    System.out.print("Y");
  }
  • 这种方法有什么问题?
  • 从现在开始如何避免此类问题?

2 个答案:

答案 0 :(得分:2)

此代码存在一些问题。我怀疑你是想写这样的东西:

public static synchronized void main(String[] args) throws InterruptedException {
  System.out.print("X");
  Thread.sleep(10000);
  System.out.print("Y");
}

Thread.sleep()方法将暂停指定时间间隔的当前线程。 Object.wait()完全是另一回事,这不太可能是你想要的。

你可以看到我如何消除线程t。如果你真的想创建一个单独的线程并在该线程上生成打印输出,那么你需要给线程做一些事情。最简单的方法是覆盖线程的run()方法,并在那里有线程代码:

public static synchronized void main(String[] args) {
  Thread t = new Thread() {
    public void run() {
      System.out.print("X");
      try { Thread.sleep(10000); } catch (InterruptedException e) { }
      System.out.print("Y");
    }
  };

  t.start();
}

如上所述,您的原始代码实际上是在创建一个没有线程主体的线程,所以当您调用t.start()时,空线程只会在后台启动,然后立即死掉。

请注意,我现在必须为InterruptedException添加一个try / catch子句,因为sleep调用已迁移到线程内部。 run()不允许抛出异常现在,不幸的是,我们必须捕获并忽略异常。

另一种写这种方法的方法是在线程t中完成一些工作,在主线程中完成其余的工作。下面是一个如何将工作拆分为两个线程的示例:

public static synchronized void main(String[] args) throws InterruptedException {
  Thread t = new Thread() {
    public void run() {
      System.out.print("X");
      try { Thread.sleep(10000); } catch (InterruptedException e) { }
    }
  };

  t.start();
  t.join();

  System.out.print("Y");
}

当它调用t.join()时,它将等待线程完成执行,这将花费10秒钟,因为它正在休眠。线程完成后,join()方法将返回并允许主线程继续。最终结果对用户显示相同:程序将打印X,暂停10秒,然后打印Y.

答案 1 :(得分:1)

好吧,约翰的建议会做的事情。但是对于发生的异常,您可能仍会感到模糊。为此,我希望您阅读Object.wait()方法和IllegalMonitorStateException的文档。

阅读完之后,你可能会想到一个问题,那就是对象的监视器到底是什么。所以这里来自wikibooks

  

每个对象都有一个“对象监视器”。基本上它是一个   '信号量',表明是否有关键   段代码正在由a执行   线程与否。在批评之前   部分可以执行,线程   必须获得'对象监视器'。只要   一次一个线程可以拥有它   对象的监视器。