我想要一个从父线程到线程池中Callable的通信管道。然而,管道从一开始就显示为"未连接"。如果我使用Runnable,问题就消失了…
我提取了一个简化的例子:
public class Test {
public static void main (String[] args) throws IOException, InterruptedException {
ExecutorService es = Executors.newCachedThreadPool();
PipedInputStream a = new PipedInputStream();
// create a list of Callables (one element) and invoke them
Son x=new Son(a);
List<Callable<Object>> ls = new LinkedList<>(); ls.add(x); es.invokeAll(ls);
// create a line oriented pipe
PrintWriter toSon =
new PrintWriter(
new BufferedWriter(
new OutputStreamWriter(
new PipedOutputStream(a))),true);
//write anything
toSon.println("blah blah blah");
//here you can add a Thread.sleep, no change
toSon.close();
}
}
:儿子public class Son implements Callable<Object> {
PipedInputStream x;
public Son(PipedInputStream x) {
this.x=x;
}
public Object call() {
BufferedReader b = new BufferedReader(
new InputStreamReader(
new BufferedInputStream(x)));
try {
System.out.println(">"+b.readLine());
} catch (IOException e) {
e.printStackTrace();
}
return null;
}
}
下面是堆栈跟踪,它对应于子句中的readln:
java.io.IOException: Pipe not connected
at java.io.PipedInputStream.read(PipedInputStream.java:306)
at java.io.PipedInputStream.read(PipedInputStream.java:378)
at java.io.BufferedInputStream.read1(BufferedInputStream.java:273)
at java.io.BufferedInputStream.read(BufferedInputStream.java:334)
at sun.nio.cs.StreamDecoder.readBytes(StreamDecoder.java:283)
at sun.nio.cs.StreamDecoder.implRead(StreamDecoder.java:325)
at sun.nio.cs.StreamDecoder.read(StreamDecoder.java:177)
at java.io.InputStreamReader.read(InputStreamReader.java:184)
at java.io.BufferedReader.fill(BufferedReader.java:154)
at java.io.BufferedReader.readLine(BufferedReader.java:317)
at java.io.BufferedReader.readLine(BufferedReader.java:382)
at prova.Son.call(Son.java:23)
at java.util.concurrent.FutureTask.run(FutureTask.java:262)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1145)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:615)
at java.lang.Thread.run(Thread.java:745)
帮忙吗?谢谢你!
在调用invokeAll()之前创建PipedOutputStream
我发现我的错误,但我不明白的症状:-/
错误在于我忘记了"invokeAll"只在所有线程完成时返回:所以"blah blah blah"永远不会发送,这不是我所期望的。但是我不明白为什么在子程序中会抛出异常。
解决方案是简单地替换行:
List<Callable<Object>> ls = new LinkedList<>(); ls.add(x); es.invokeAll(ls);
加一个普通的
es.submit(x);
或使用适当的while循环来处理可运行的集合,就像我的实际情况一样(还没有尝试…)。
EJP的(错误)答案给了我一个相关的线索,因为在这种情况下,没有欺骗的症状,只是一个意想不到的结果。