带有两个线程的IllegalMonitorStateException

时间:2012-03-01 11:01:03

标签: java multithreading

我的程序有两个Threads,每个都打印十个数字。第一个Thread打印奇数,第二个Thread打印偶数,然后轮流打印数字。我希望得到像1,2,3,4,5 ......这样的序列,直到20,但程序会产生IllegalMonitorStateException。

我知道此Exception的含义,但我在synchronized块中使用wait()notify()。这是我的代码:

     public class EvenOddThreadTest {

      /**
       * @param args
       */
      static Object obj1 = new Object();
      static Object obj2 = new Object();
      static Object obj3=new EvenOddThreadTest();

      public static void main(String[] args) throws InterruptedException {
          new Thread() {
              @Override
              public void run() {

                      for (int i = 1; i < 21; i += 2) {
                          synchronized (obj1) {
                          System.out.println(i + Thread.currentThread().getName());
                          try {
                              obj2.notify();                    
                              obj1.wait();
                          } catch (InterruptedException e) {
                              e.printStackTrace();
                          }

                      }
                  }
              }
          }.start();
          new Thread() {
              @Override
              public void run() {
                      for (int i = 2; i < 21; i += 2) {
                          synchronized (obj2) {

                          System.out.println(i + Thread.currentThread().getName());
                        try {
                            obj1.notify();
                            obj2.wait();
                        } catch (InterruptedException e) {
                            e.printStackTrace();
                        }
                    }
                }
            }

            }.start();
        }
    }

这是生成的异常:

1Thread-0
2Thread-1
Exception in thread "Thread-0" java.lang.IllegalMonitorStateException
    at java.lang.Object.notify(Native Method)
    at EvenOddThreadTest$1.run(EvenOddThreadTest.java:21)
Exception in thread "Thread-1" java.lang.IllegalMonitorStateException
    at java.lang.Object.notify(Native Method)
    at EvenOddThreadTest$2.run(EvenOddThreadTest.java:41)

我无法弄清楚这一点。有什么想法吗?

4 个答案:

答案 0 :(得分:4)

您无法对您不拥有的显示器的对象发送通知:

               synchronized (obj1) {
                  System.out.println(i + Thread.currentThread().getName());
                  try {
                      obj2.notify();  // You haven't synchronized on obj2 

答案 1 :(得分:3)

如果两个线程一起工作,则它们需要在同一个变量上进行同步。你想要的是等待轮到它运行,然后运行,然后通知另一个线程。

public class EvenOddThreadTest {

  /**
   * @param args
   */
  static Object obj1 = new Object();
  static Object obj3=new EvenOddThreadTest();

  public static void main(String[] args) throws InterruptedException {
      new Thread() {
          @Override
          public void run() {

                  for (int i = 1; i < 21; i += 2) {
                      synchronized (obj1) {
                      try {
                          while (/* not my turn to run *?*/) {                   
                             obj1.wait();
                          }
                      } catch (InterruptedException e) {
                          e.printStackTrace();
                      }
                      System.out.println(i + Thread.currentThread().getName());
                      obj1.notify();
                  }
              }
          }
      }.start();
      new Thread() {
          @Override
          public void run() {
                  for (int i = 2; i < 21; i += 2) {
                      synchronized (obj1) {
                      try {
                          while (/* not my turn to run *?*/) {                   
                             obj1.wait();
                          }
                      } catch (InterruptedException e) {
                          e.printStackTrace();
                      }
                      System.out.println(i + Thread.currentThread().getName());
                      obj1.notify();
                }
            }
        }

        }.start();
    }
}

答案 2 :(得分:0)

在主题0中,您只是在obj2而不是obj1上同步notify。在第二个线程中,它是另一种方式。

答案 3 :(得分:0)

这不会直接回答你的问题,但是线程很低。在您的情况下,您可以使用CyclicBarrier,它将为您处理同步详细信息:

public class Test {

    static CyclicBarrier barrier = new CyclicBarrier(2);

    public static void main(String[] args) throws InterruptedException {
        new Thread() {

            @Override
            public void run() {
                try {
                    for (int i = 1; i < 21; i += 2) {
                        System.out.println(i + Thread.currentThread().getName());
                        barrier.await();
                    }
                } catch (BrokenBarrierException e) {
                    //do something
                } catch (InterruptedException e) {
                    //do something
                }
            }
        }.start();
        new Thread() {

            @Override
            public void run() {
                try {
                    for (int i = 2; i < 21; i += 2) {
                        barrier.await();
                        System.out.println(i + Thread.currentThread().getName());
                    }
                } catch (BrokenBarrierException e) {
                    //do something
                } catch (InterruptedException e) {
                    //do something
                }
            }
        }.start();
    }
}