我怀疑问题是外部进程(连接到proc
) 或者是
- 不读取其标准输入,或者
- 它正在向其标准输出写入 Java 应用程序未读取的内容。
请记住,Java 使用一对“管道”与外部进程通信,并且这些管道的缓冲量有限。如果超出管道的缓冲容量,写入进程将被阻止写入管道,直到读取进程从管道读取足够的数据以腾出空间。如果读取器不读取,则管道将锁定。
如果您提供更多上下文(例如启动 gzip 进程的应用程序部分),我将能够更加明确。
FOLLOWUP
gzip.exe 是我们使用的 Windows 中的一个 UNIX 实用程序。命令提示符下的 gzip.exe 工作正常。但java程序不行。有什么方法可以增加 java 写入管道的缓冲大小。我目前关心的是输入部分。
在 UNIX 上,gzip 实用程序通常使用以下两种方式之一:
-
gzip file
压缩file
把它变成file.gz
.
-
... | gzip | ...
(或类似的东西)将其标准输入的压缩版本写入其标准输出。
我怀疑你正在做与后者相同的事情,用java应用程序作为源gzip
命令的输入及其输出的目的地。如果 java 应用程序没有正确实现,这正是可能锁定的场景。例如:
Process proc = Runtime.exec(...); // gzip.exe pathname.
OutputStream out = proc.getOutputStream();
while (...) {
out.write(...);
}
out.flush();
InputStream in = proc.getInputStream();
while (...) {
in.read(...);
}
如果上面应用程序的写入阶段写入了太多数据,那么肯定会锁定。
java应用程序之间的通信gzip
是通过两个管道。正如我上面所说,管道将缓冲一定量的数据,但该量相对较小,并且肯定是有限的。这就是锁机的原因。发生的情况如下:
- The
gzip
进程是通过一对将其连接到 Java 应用程序进程的管道创建的。
- Java 应用程序将数据写入其
out
stream
- The
gzip
进程从其标准输入读取数据,对其进行压缩并写入其标准输出。
- 步骤2.和3.重复几次,直到最后
gzip
进程尝试写入其标准输出块。
正在发生的事情是gzip
一直在写入其输出管道,但没有从其中读取任何内容。最终,我们到达了耗尽输出管道的缓冲区容量并且写入管道的时间点。
与此同时,Java 应用程序仍在写入out
流式传输,再进行几轮后,这也会阻塞,因为我们已经填充了另一个管道。
唯一的解决方案是Java应用程序读写同时。执行此操作的简单方法是创建第二个线程,并从一个线程写入外部进程并从另一个线程中的进程读取。
(更改 Java 缓冲或 Java 读/写大小不会有帮助。重要的缓冲是在管道的操作系统实现中,并且没有办法从纯 Java 中更改它(如果有的话)。)