Чтение стандартного вывода nodejs из Java (используя apache commons exec). Поток безопасен или нет? - PullRequest
1 голос
/ 13 мая 2019

Я пытаюсь написать клиент торрентной потоковой передачи на Java с помощью webtorrent-cli, который работает на NodeJS.При установке в качестве модуля узла webtorrent-cli предоставляет хороший webtorrent.cmd скрипт, который можно использовать для работы с ним.Когда начинается загрузка для торрента, клиент каждую секунду обновляет стандартный вывод с полезными подробностями, такими как скорость загрузки,% загруженного торрента, доступные семена и т.д.exec), я использую следующий фрагмент:

private static Thread processCreator() {
    return new Thread(() -> {
        try {
            // Read stdout in a thread safe manner (hopefully)
            final ByteArrayOutputStream baos = new ByteArrayOutputStream();
            PumpStreamHandler handler = new PumpStreamHandler(baos);

            String command = getCommand();
            CommandLine cmd = CommandLine.parse(command);

            Executor cmdExecutor = new DefaultExecutor();
            cmdExecutor.setStreamHandler(handler);

            // Schedule a service to print the content of baos each second
            final ScheduledExecutorService service = Executors.newSingleThreadScheduledExecutor();
            service.scheduleAtFixedRate(() -> {
                try {
                    // Read and reset atomically
                    synchronized (baos) {
                        System.out.println(baos.toString("UTF-8"));

                        // Resetting so that buffer size doesn't grow arbitrarily
                        baos.reset();
                    }
                }
                catch (UnsupportedEncodingException e) {
                    e.printStackTrace();
                }
            }, 0, 1, TimeUnit.SECONDS);

            cmdExecutor.execute(cmd);

            // Let the remaining bytes be processed
            sleep(1000);

            // Shutdown
            service.shutdown();
        } catch (IOException ioe) {
            ioe.printStackTrace();
        }
    });
}

public static void main(String[] args) throws InterruptedException {
    Thread process = processCreator();
    process.start();
    process.join();
}

Я обеспокоен тем, как пишется ByteArrayOutputStream.Сам класс является поточно-ориентированным, но если реализация выполняет запись в буфер побайтно или таким образом, что «обновленный вывод» (из webtorrent-cli) только частично записывается в буфер к тому времени, когда запланированная служба захватывает монитор иначинает обработку, то это вызовет проблемы.В этом случае, потому что я просто печатаю содержимое буфера, я думаю, это не составит большого труда.Но я должен обработать вывод и извлечь пару деталей в фиксированном запланированном сервисе.Я могу придумать другой способ для достижения надлежащей координации (например: наблюдать за полнотой обновления, отмечая событие, когда буфер получает байты, которые формируют первую строку в stdout webtorrent-cli ... и отмечать обновление как выполненное, когдабуфер получает байты, которые формируют последнюю строку. Каждое обновление имеет идентичные первую и последнюю строки ... или, по крайней мере, несколько байтов в начале и конце идентичны).Но это было бы немного больше работы, чем это.У меня вопрос, могу ли я быть уверен, что запись в буфер произошла за один атомарный вызов ByteArrayOutputStream.write(byte[], ...) '.Надеюсь, я достаточно хорошо объяснил свой вопрос.Если вам нужно больше деталей, дайте мне знать в комментариях.Кстати, когда код, приведенный выше, выполняется, вывод показывает, что координация должным образом управляется.Но, может быть, мне просто повезло, что условия гонки до сих пор избегались?

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...