2012-04-15 12 views
2

私がしようとしているのは、スレッドが親スレッドから受け取ったメッセージをOutputStreamに書き込んだり、返信用のInputStreamを聴いたり、親スレッドに応答を通知したりすることです。私は、似たようなことをするテストクラスを2つ書いていますが、異なる方法で簡単です。 方法1は、デバッグステートメント"before loop"のコメントが解除されている場合にのみ機能し、方法2は"message from child"デバッグステートメントのみを出力します。私は間違って何をしていますか?スレッド間メッセージングの実装

方法1

public class Parent { 
    private static int out = 0; 
    private static int in = 0; 

    public static void main(String[] args) { 
     final Object locker = new Object(); 
     Thread t = new Thread(new Runnable() {   
      @Override 
      public void run() { 
       while (true) { 
        synchronized (locker) { 
         try { 
          locker.wait(); 
          System.out.println("Message from parent " + out); 
          in = out + 10; 
          locker.notify(); 
         } catch (InterruptedException e) { 
          // TODO Auto-generated catch block 
          e.printStackTrace(); 
         } 
        } 
       } 
      } 
     }); 
     t.start(); 

     System.out.println("before loop"); 
     while (out < 10) { 
      synchronized (locker) { 
       locker.notify(); 
       try { 
        locker.wait(); 
        out++; 
        System.out.println("Message from child " + in); 
       } catch (InterruptedException e) { 
        // TODO Auto-generated catch block 
        e.printStackTrace(); 
       }    
      } 
     }  
    } 
} 

方法子供が行う前に、親スレッドがその最初のnotify()を行うことができますので、あなたは、デッドロックのために良いレシピを持っている方法1では2

public class Parent { 

    /** 
    * @param args 
    * @throws InterruptedException 
    */ 
    public static void main(String[] args) throws InterruptedException { 
     final BlockingQueue<Integer> q = new ArrayBlockingQueue<Integer>(1); 

     Thread t = new Thread(new Runnable() {   
      @Override 
      public void run() { 
       while (true) { 
        try { 
         Integer i = q.take();    
         System.out.println("Message from parent: " + i.intValue()); 
         q.put(i.intValue() + 10); 
        } catch (InterruptedException e) { 
         // TODO Auto-generated catch block 
         e.printStackTrace(); 
        } 
       }    
      } 
     }); 

     for (int i = 0; i < 10; i++) { 
      q.put(i); 
      Integer j = q.take(); 
      System.out.println("Message from child: " + j); 
     } 
    } 

} 

答えて

5

Java APIはすでにその機能を提供しています。あなたは車輪を再発明する正当な理由がありますか?

public static void main(String[] args) throws Exception { 
    // start a worker thread 
    ExecutorService exec = Executors.newFixedThreadPool(1); 

    // ask the worker thread to execute a task (
    Future<String> future = exec.submit(() -> { 
     Thread.sleep(500); // simulate waiting for I/O 
     return "hello from child"; 
    }); 

    // get the return value from the worker thread (waiting until it is available) 
    String greeting = future.get(); 
    System.out.println(greeting); 

    // terminate the worker thread (otherwise, the thread will wait for more work) 
    exec.shutdown(); 
} 
+0

本当に、私はちょうど十分にJavaをよく知りません:-)ありがとう! – Johnny

1

その最初のwait()。これにより、どちらも待機することはなく、通知することもできません。競合状態であるため、printステートメントのような些細なことが実際の動作に影響する可能性があります。

同じキューからのスレッドの書き込みと読み取りの両方があるため、方法2も同様に設計が不適切です。 2つのキュー(親が書き込む子と子が読み込むキュー)と、子が書き込む親と親が読み込むキューを試してください。

関連する問題