我要做的是让一个线程将从其父线程收到的消息写入一个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);
}
}
}
答案 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的设计也很差,因为你有两个线程在同一个队列中写入和读取。尝试使用两个队列,一个是父级写入并且子级读取,另一个是子级写入,父级读取。