从 shell 脚本生成的 Java InputStream 中读取是分批进行的

Reading from a Java InputStream generated by a shell script happens in batches

我正在尝试通过 Java 程序在 Raspberry Pi 上编排 Python 脚本。我有一些 Python 代码,里面有一个无限循环,可以读取超声波传感器的距离并将其输出到控制台。 Java 代码将其称为 shell 进程,然后读取进程的 OutputStream。我遇到的问题是数据成批到达。我不是每次 Python 脚本输出到控制台时都获得一个新值,而是每 10 秒左右获得一次新数据。这是有问题的,因为我试图在网络仪表板上近乎实时地显示数据。

图表如下所示:

DistanceController
    |--getDistance(public)
    |--getBufferSize(public)
    |--buffer(private)
    |--DistanceThread(private)
            |--bufferReference (private)
            |--PythonScriptProcess

Java代码如下:

这是一个包装器 class,它实例化一个新线程(单独的 class)以从 Python 脚本的输出流中读取。

public class DistanceController {
    private DistanceThread distanceThread;
    private Thread t;
    private LinkedList<DistanceVT>  buffer = new LinkedList<DistanceVT>();

    public DistanceController()
    {            
        t = new Thread(distanceThread);
        t.start();
    }

    public DistanceVT getDistance() {
        return buffer.getLast();
    }
}

这是读取距离的线程,思路是非阻塞的。

public class DistanceThread implements Runnable {
private LinkedList<DistanceVT> buffer;
private String[] args = new String[]{"python", "./run-scripts/distance.py"};

public DistanceThread(LinkedList<DistanceVT> list) {buffer = list;}

@Override
public void run() {
    while (true) {
        try {
            ProcessBuilder pb = new ProcessBuilder(args);
            pb.redirectErrorStream(true);
            final Process p = pb.start();
            while (true) {
                InputStream s = p.getInputStream();
                final BufferedReader reader = new BufferedReader(new InputStreamReader(s));
                while (((line = reader.readLine()) != null)) {
                    buffer.add(parseDistance(line));
                }
            }
        } catch (Exception e) {
        //handle errors
        }
    }
}

而 Python 代码看起来像这样(最简单的距离测量代码的稍微修改版本):

import time
import datetime
from random import randint

def measure_distance():
    time.sleep(0.1)
    return randint(10,15)

while True:
    distance = measure_distance()
    print ("%s,%s" % (datetime.datetime.now(),distance))

谢谢大家的帮助。 EJP 解决了缓冲问题 - 在 Python 代码中添加 sys.stdout.flush() 解决了问题。

至于其他问题-你是对的。我的意思是因为我是在一个单独的线程上阅读,程序的主线程可以继续做其他逻辑。

读取线程将数据累积在创建它的 class 传递给它的列表中。然后可以通过此包装器访问此数据 class,而无需等待输出完成。

import time
import datetime
from random import randint
import sys

def measure_distance():
    time.sleep(0.1)
    return randint(10,15)

while True:
    distance = measure_distance()
    print ("%s,%s" % (datetime.datetime.now(),distance))
    sys.stdout.flush()