如何通知PipedOputputStream线程已写入最后一个字节的PipedInputStream线程?

时间:2012-03-29 09:32:07

标签: java multithreading pipe

如何在管道的输出端正确完成工作?我需要写入线程来终止或做一些其他的工作,而读取线程读取所有写入的数据。

我应该在写入端关闭管道还是什么?

更新1

我想澄清......根据给出的答案,我是否正确地认为按设计管道行为并不假设任何优雅的终止?

即。一旦打开,停止管道的唯一方法就是打破管道?

read()方法返回-1时,常规流期望流信号结束。我认为管道流不会发生这种情况吗?

3 个答案:

答案 0 :(得分:5)

是的,关闭PipedOutputStream会在PipedInputStream上产生-1。

看起来很优雅!这是我的SSCCE

import java.io.*;
import java.nio.charset.*;

public class SOPipe
{
    public static void main(String[] args) throws Exception
    {
        PipedOutputStream os = new PipedOutputStream();
        PipedInputStream is = new PipedInputStream(os);

        ReaderThread readerThread = new ReaderThread(is);
        WriterThread writerThread = new WriterThread(os);

        readerThread.start();
        writerThread.start();

        readerThread.join();
        writerThread.join();

        System.out.println("Both Reader and Writer completed.");
        System.out.println("Main method returning normally now.");
    }

    private static final Charset LATIN1 = Charset.forName("latin1");

    public static class WriterThread extends Thread
    {
        private final PipedOutputStream _os;

        public WriterThread(PipedOutputStream os)
        {
            _os = os;
        }

        public void run()
        {
            try
            {
                String msg = "Ceci n'est pas une pipe";
                byte[] msgBytes = msg.getBytes(LATIN1);
                System.out.println("WriterThread sending message: " + msg);
                for(int i = 0; i < msgBytes.length; i++)
                {
                    _os.write(msgBytes, i, 1);
                    System.out.println("WriterThread wrote a byte!");
                    _os.flush();
                }
                _os.close();
                System.out.println("[COMPLETED] WriterThread");
            }
            catch (Exception e)
            {
                e.printStackTrace();
            }
        }
    }

    public static class ReaderThread extends Thread
    {
        private final PipedInputStream _is;

        public ReaderThread(PipedInputStream is)
        {
            _is = is;
        }

        public void run()
        {
            try
            {
                ByteArrayOutputStream baos = new ByteArrayOutputStream();
                byte[] buffer = new byte[1];
                int read;
                while ((read = _is.read(buffer, 0, 1)) != -1)
                {
                    System.out.println("ReaderThread read a byte!");
                    baos.write(buffer, 0, read);
                }
                System.out.println("[COMPLETED] ReaderThread; received: " 
                        + new String(baos.toByteArray(), LATIN1));
                _is.close();
            }
            catch (Exception e)
            {
                e.printStackTrace();
            }
        }
    }
}

答案 1 :(得分:4)

仅关闭输出流就足够了。

答案 2 :(得分:0)

您可以延长PipedOutputStream课程&amp;在将所有字节写入管道输出流之后,覆盖其write()方法以添加自定义逻辑。

    public class CustomPipedOutput extends PipedOutputStream {

          @Override
          public void write(byte[] byteArray, int offset, int length){

            super.write(byteArray, offset, length);

            //-- Code to be executed after writing bytes
          }

          @Override
          public void close(){

            super.close();

            //-- Code to be executed after closing piped input stream
          }

   }

同样,如果需要,可以扩展其他方法。