2012-03-01 66 views
0

我的程序有兩個線程,每個線程打印十個數字。第一條線打印奇數,第二條線打印偶數,然後輪流打印數字。我期待得到像1,2,3,4,5 ....直到20的序列,但程序產生IllegalMonitorStateException。有兩個線程的IllegalMonitorStateException

我知道這個異常是什麼意思,但我在同步塊中使用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) 

我不知道這一點。有任何想法嗎?

回答

3

不能調用notify一個對象,其監測你沒有自己的:

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

在線程0你只同步在其上調用notifyobj2obj1。在第二個線程中,它是相反的。

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(); 
    } 
} 
+0

這不會控制誰先運行,只是確保兩個線程在打印第二個數字之前打印第一個數字。 – 2012-03-02 22:56:07

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(); 
    } 
}