Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/338.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 如何使用进程';作为一个流,没有阻塞吗?_Java_Processbuilder - Fatal编程技术网

Java 如何使用进程';作为一个流,没有阻塞吗?

Java 如何使用进程';作为一个流,没有阻塞吗?,java,processbuilder,Java,Processbuilder,在Java(或clojure)中,我希望启动一个外部进程,并将其stdout作为流使用。理想情况下,我希望在外部进程每次刷新时都使用进程的输出流,但不确定如何实现,以及如何在不阻塞的情况下实现 例如,我发现继承的InputStream方法使用起来有点低级,并且不确定是否有一种非阻塞的方式在每次生产者端刷新时从流中使用,或者以非阻塞的方式使用 许多代码示例在一个无限循环中阻塞输出流,从而占用一个线程进行侦听。我希望这种阻塞行为可以完全避免 底线: 是否有一种非阻塞方式可以在输入流的生成端每次刷新时

在Java(或clojure)中,我希望启动一个外部进程,并将其stdout作为流使用。理想情况下,我希望在外部进程每次刷新时都使用进程的输出流,但不确定如何实现,以及如何在不阻塞的情况下实现

例如,我发现继承的
InputStream
方法使用起来有点低级,并且不确定是否有一种非阻塞的方式在每次生产者端刷新时从流中使用,或者以非阻塞的方式使用

许多代码示例在一个无限循环中阻塞输出流,从而占用一个线程进行侦听。我希望这种阻塞行为可以完全避免

底线:
是否有一种非阻塞方式可以在输入流的生成端每次刷新时得到通知

您需要创建一个单独的线程,该线程将使用这样一个流,从而允许程序的其余部分并行地执行任何需要执行的操作

class ProcessOutputReader implements Runnable {

   private InputStream processOutput;

   public ProcessOutputReader(final InputStream processOutput) {
       this.processOutput = processOutput;
   } 

   @Override
   public void run() {
      int nextByte;
      while ((nextByte = processOutput.read()) != -1) {
        // do whatever you need to do byte-by-byte.
        processByte(nextByte);
      }
   }
}

class Main {
   public static void main(final String[] args) {
       final Process proc = ...; 
       final ProcessOutputReader reader = new ProcessOutputReader(proc.getInputStream());
       final Thread processOutputReaderThread = new Thread(reader);
       processOutputReaderThread.setDaemon(true); // allow the VM to terminate if this is the only thread still active.
       processOutputReaderThread.start();
       ...
       // if you wanna wait for the whole process output to be processed at some point you can do this:
       try {
         processOutputReaderThread.join();
       } catch (final InterruptedException ex) {
         // you need to decide how to recover from if your wait was interrupted.
       }
   }
}
如果不是逐字节处理,而是希望将每个刷新作为一个单独的部分处理。。。我不确定是否有100%的保证能够捕获每个进程刷新。毕竟,进程自己的IO框架软件(Java、C、Python等)可能会以不同的方式处理“刷新”操作,并且最终可能会收到该外部进程中任何给定刷新的多个字节块

在任何情况下,您都可以尝试使用
InputStream
available
方法来实现这一点,如下所示:

   @Override
   public void run() {
      int nextByte;
      while ((nextByte = processOutput.read()) != -1) {
        final int available = processOutput.available();
        byte[] block = new byte[available + 1];
        block[0] = nextByte;
        final int actuallyAvailable = processOutput.read(block, 1, available);
        if (actuallyAvailable < available) { 
          if (actuallyAvailable == -1) { 
            block = new byte[] { nextByte };
          } else {
            block = Arrays.copyOf(block, actuallyAvailable + 1);
          } 
        }
        // do whatever you need to do on that block now.
        processBlock(block);
      }
   }
@覆盖
公开募捐{
int-nextByte;
而((nextByte=processOutput.read())!=-1){
final int available=processOutput.available();
字节[]块=新字节[可用+1];
块[0]=下一个字节;
final int actuallyAvailable=processOutput.read(块1,可用);
如果(实际可用<可用){
如果(实际可用==-1){
块=新字节[]{nextByte};
}否则{
block=Arrays.copyOf(block,实际可用+1);
} 
}
//现在在那个街区做你需要做的一切。
进程块(块);
}
}
我不是100%确定这一点,但我认为不能相信
available
将返回一个保证的字节数下限,您可以在不被阻塞的情况下检索该字节数,也不能相信下一个
read
操作将返回该字节数(如果请求);这就是为什么上面的代码检查实际读取的字节数(
actuallyAvailable