2012-04-15 97 views
2

我想要做的是让一个线程将它从父线程接收到的消息写入一个OutputStream,监听一个InputStream的回复,然后通过回复通知父线程。我写了两个测试类,它们以不同的方式做类似但更简单的测试。 方法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(); 
       }    
      } 
     }  
    } 
} 

方法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 2012-04-15 15:10:52

1

在方法1你有一个好的食谱僵局,因为孩子不前父线程可以执行其第一notify()其第一个wait()。这将导致他们两人都在等待,既无法通知。由于这是一种竞争条件,因此打印语句等微不足道的事情可能会影响实践中的行为。

方法2同样设计不好,因为你有两个线程都从同一队列写入和读取。尝试使用两个队列,一个是父项写入和子项读取,另一个是子项写入和父项读取。