管道输入流被锁定

Dhe*_*shi 2 java stream

我试图使用管道输入流写入数据.但是从线程转储看起来管道输入流上有一个锁.

PipedOutputStream pos = new PipedOutputStream();
PipedInputStream pis = new PipedInputStream(pos);
FileInputStream fis = null;
GZIPOutputStream gos = null;
byte[] buffer = new byte[1024];
try {
    fis = new FileInputStream(file);
    gos = new GZIPOutputStream(pos);
    int length;
    while ((length = fis.read(buffer, 0, 1024)) != -1)
        gos.write(buffer, 0, length);
    } catch(Exception e){
        print("Could not read the file");
    }
    finally {
        try {
            fis.close();
            gos.close();
        }catch (Exception ie){ 
            printException(ie);
        }
    }
writeObject(pis);
pos.close();
Run Code Online (Sandbox Code Playgroud)

writeobj方法将简单地从流中读取,但read方法被锁定.线程转储表明管道输入流有一些等待.

main" prio=10 tid=0x08066000 nid=0x48d2 in Object.wait() [0xb7fd2000..0xb7fd31e8]
   java.lang.Thread.State: TIMED_WAITING (on object monitor)
    at java.lang.Object.wait(Native Method)
    - waiting on <0xa5c28be8> (a java.io.PipedInputStream)
    at java.io.PipedInputStream.awaitSpace(PipedInputStream.java:257)
    at java.io.PipedInputStream.receive(PipedInputStream.java:215)
    - locked <0xa5c28be8> (a java.io.PipedInputStream)
    at java.io.PipedOutputStream.write(PipedOutputStream.java:132)
    at java.util.zip.GZIPOutputStream.finish(GZIPOutputStream.java:95)
    at java.util.zip.DeflaterOutputStream.close(DeflaterOutputStream.java:146)

   Locked ownable synchronizers:
    - None
Run Code Online (Sandbox Code Playgroud)

我不确定是谁锁定了它.阅读文档以找出锁定调用.但无法弄清楚出了什么问题以及如何克服它.

til*_*lex 7

使用PipedInputStream和PipedOutputStream必须位于不同的线程中.

仔细阅读Javadoc:http: //docs.oracle.com/javase/6/docs/api/java/io/PipedInputStream.html

通常,一个线程从PipedInputStream对象读取数据,并且某些其他线程将数据写入相应的PipedOutputStream.建议不要尝试使用单个线程中的两个对象,因为它可能使线程死锁.


Boa*_*ann 5

PipedInputStream 有一个小的非扩展缓冲区。一旦缓冲区已满,写入 PipedOutputStream 块,直到缓冲的输入被不同的线程读取。您不能在同一个线程中使用这两个,因为写入将等待不可能发生的读取。

在您的情况下,您在写入所有数据之前不会读取任何数据,因此解决方案是使用ByteArrayOutputStreamByteArrayInputStream代替:

  1. 将所有数据写入 ByteArrayOutputStream。
  2. 完成后,在流上调用 toByteArray() 以检索字节数据。
  3. (可选)使用字节数据创建一个 ByteArrayInputStream,以作为 InputStream 从中读取。

  • 如果数据以千兆字节为单位怎么办?(应用程序肯定会崩溃)创建流是为了防止分配大内存块。 (2认同)