java - 当我向水槽写入无原因时,java管道抛出"破碎管道" 如何调试? !

  显示原文与译文双语对照的内容
94 0

我相信我已经正确地完成了一切。 在 selector thread创建管道,将接收器传递给写入线程,用在选择器上创建源,然后启动选择器。 一切工作都可以,但一旦我把一些东西写到水槽里,就会得到一个破坏的管道异常。 啊这里没有破碎的管道。 ! 我很失败。如何调试/理解这里发生了什么? 谁有一个简单的管道示例,我可以运行它来测试是否工作正常。 在接收器上写入的线程和读取器读取它。

我几乎遵循这里建议的 很难在因特网上找到NIO管道的具体示例。


import java.io.*;


import java.nio.ByteBuffer;


import java.nio.channels.*;


import java.util.Iterator;



public class SystemOutPipe extends Thread {



 public static void main(String[] args)


 {


 try {


 SystemOutPipe sop = new SystemOutPipe();


 sop.start();


 System.out.println("This message should be redirected to System.errnNow waiting 5 seconds.. .");


 Thread.sleep(5000L);


 sop.setStopped(true);


 sop.join();


 } catch (Exception e) {


 e.printStackTrace();


 }


 }



 private Selector selector;


 private Pipe pipe;


 private boolean stopped = false;



 public SystemOutPipe() throws IOException {


 super("SystemOutPipe");


 pipe = Pipe.open();


 System.setOut(new PrintStream(new PipeOutputStream(pipe)));


 selector = Selector.open();


 pipe.source().configureBlocking(false);


 pipe.source().register(selector, SelectionKey.OP_READ, ByteBuffer.allocate(1024));


 }



 @Override


 public void run() {


 try {


 while (!isStopped()) {


 int n = selector.select(1L);


 if (n> 0) {


 Iterator<SelectionKey> it = selector.selectedKeys().iterator();


 while (it.hasNext()) {


 SelectionKey key = it.next();


 it.remove();


 if (key.isReadable()) {


 new ReadHandler(key).run();


 }


 }


 }


 }


 } catch (Exception e) {


 e.printStackTrace();//writes to System.err!


 }


 }



 public synchronized boolean isStopped() {


 return stopped;


 }



 public synchronized void setStopped(final boolean stopped) {


 this.stopped = stopped;


 }



 public class ReadHandler implements Runnable {


 private final SelectionKey key;



 public ReadHandler(final SelectionKey key) {


 this.key = key;


 }



 @Override


 public void run() {


 ByteBuffer bbuf = (ByteBuffer) key.attachment();


 ReadableByteChannel channel = (ReadableByteChannel) key.channel();


 try


 {


 int count = 0;


 do {


 bbuf.clear();


 count = channel.read(bbuf);


 if (count> 0) System.err.write(bbuf.array(), 0, count);


 } while(count> 0);


 } catch (IOException e) {


 e.printStackTrace();


 key.cancel();


 }


 }


 }



 public class PipeOutputStream extends OutputStream {


 private final Pipe pipe;



 public PipeOutputStream(final Pipe pipe) {


 this.pipe = pipe;


 }



 @Override


 public void write(final int b) throws IOException {


 write(new byte[] { (byte) b });


 }



 @Override


 public void write(final byte[] b) throws IOException {


 write(b, 0, b.length);


 }



 @Override


 public void write(final byte[] b, final int off, final int len) throws IOException {


 ByteBuffer bbuf = ByteBuffer.wrap(b, off, len);


 bbuf.position(len);


 bbuf.flip();


 int count = 0;


 while (count <len) {


 int n = pipe.sink().write(bbuf);


 if (n == 0) {


//let's wait a bit and not consume cpu


 try {


 Thread.sleep(1L);


 } catch (InterruptedException e) {


 throw new IOException(e);


 }


 }


 else count += n;


 }


 }


 }


}



异常:


java.io.IOException: Broken pipe


 at sun.nio.ch.FileDispatcher.write0(Native Method)


 at sun.nio.ch.FileDispatcher.write(FileDispatcher.java:39)


 at sun.nio.ch.IOUtil.writeFromNativeBuffer(IOUtil.java:72)


 at sun.nio.ch.IOUtil.write(IOUtil.java:43)


 at sun.nio.ch.SinkChannelImpl.write(SinkChannelImpl.java:149)


 at com.niostuff.util.GCLogInterceptor.fileModified(GCLogInterceptor.java:180)


 at net.contentobjects.jnotify.linux.JNotifyAdapterLinux$WatchData.notifyFileModified(Unknown Source)


 at net.contentobjects.jnotify.linux.JNotifyAdapterLinux.notifyChangeEvent(Unknown Source)


 at net.contentobjects.jnotify.linux.JNotifyAdapterLinux$1.notify(Unknown Source)


 at net.contentobjects.jnotify.linux.JNotify_linux.callbackProcessEvent(Unknown Source)


 at net.contentobjects.jnotify.linux.JNotify_linux.nativeNotifyLoop(Native Method)


 at net.contentobjects.jnotify.linux.JNotify_linux.access$000(Unknown Source)


 at net.contentobjects.jnotify.linux.JNotify_linux$1.run(Unknown Source)



时间: 原作者:

100 1

好吧我发现了问题。 首先感谢所有尝试帮助的人。 希望你能从我的错误中吸取教训。 事件链是:

1 - 我没有耗尽接收缓冲区( 源频道读入的那个),它最终得到满了。

2 - 现在它已经满了,pipeSourceChannel.read(readBuffer) 返回 0字节。 要读取的数据,但不能在完整缓冲区上读取。

3 - 导致通道关闭( 我自己在 bytesRead == 0上做的) 和 BrokenPipe 。

我在这里学到了一个教训: 管道非常复杂我认为非阻塞并发队列在这里一旦提到就更容易使用了: 管道 vs

原作者:
...