线程间消息传递实现

时间:2012-04-15 13:51:38

标签: java multithreading

我要做的是让一个线程将从其父线程收到的消息写入一个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);
        }
    }

}

2 个答案:

答案 0 :(得分: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();
}

答案 1 :(得分:1)

在方法1中,你有一个很好的死锁方法,因为父线程可以在孩子完成第一个notify()之前执行它的第一个wait()。这将导致他们两个都在等待,但都无法通知。由于这是一种竞争条件,因此印刷陈述等微不足道的事情会影响实践中的行为。

方法2的设计也很差,因为你有两个线程在同一个队列中写入和读取。尝试使用两个队列,一个是父级写入并且子级读取,另一个是子级写入,父级读取。