2012-03-01 8 views
0

私のプログラムには2つのスレッドがあり、それぞれ10個の数字が出力されます。最初のスレッドは奇数を出力し、2番目のスレッドは偶数を出力し、番号を順に印刷します。私は1,2,3,4,5 ....のようなシーケンスを20まで得ることを期待していますが、プログラムはIllegalMonitorStateExceptionを生成します。2つのスレッドを持つ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

あなたは、そのモニター、あなたが所有していないオブジェクトに通知を呼び出すことはできません。スレッド0で

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

あなただけがnotifyを呼び出すにobj2ないobj1に同期しています。 2番目のスレッドでは、それは逆です。

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

誰が最初に実行するかを制御することはできません。両方のスレッドが2番目の番号を印刷する前に最初の番号を印刷するようにします。 –

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(); 
    } 
} 
関連する問題