为什么队列不在主线程上更新?

ZythiQ

我正在打开一个 PowerShell 实例并通过 System.in 向它发送命令,我想将输出收集到一个队列中,这样我就可以在不干扰输入命令的情况下打印结果。但是,队列没有在主线程上填充,并且在主线程上休眠只是稍微解决了这个问题。我想问题在于不同步队列,但我不确定如何。

package PWST;

import java.io.PrintWriter;
import java.util.LinkedList;
import java.util.Queue;
import java.util.Scanner;

public class PWST {
    public static void main(String[] args) {
        try {
            Scanner in = new Scanner(System.in);
            System.out.print("\033[H\033[2J > "); // clear console.
            String[] tokens = in.nextLine().split(",");

            Queue<String> stdout = new LinkedList<>();
            Queue<String> stderr = new LinkedList<>();

            Process process = Runtime.getRuntime().exec("powershell.exe");
            new Thread(new SPQ(process.getInputStream(), stdout)).start();
            new Thread(new SPQ(process.getErrorStream(), stderr)).start();
            PrintWriter out = new PrintWriter(process.getOutputStream());
                
            for (String token : tokens) // parse commands (will be expanded to continuously ask for input)
                out.println(token.strip());

            // print powershell output after:
            System.out.println(stdout);
            System.out.println(stderr);

            in.close();
            out.close();
            process.waitFor();
            System.out.println("Shell link closed");
            
        } catch (Exception e) { e.printStackTrace(); }
    }
}
package PWST;

import java.io.InputStream;
import java.util.Queue;

class SPQ implements Runnable {
    private Queue<String> queue;
    private InputStream istrm;

    public SPQ(InputStream istrm, Queue<String> queue) {
        this.istrm = istrm;
        this.queue = queue;
    }

    public void run() {
        try {
            final byte[] buffer = new byte[1024];
            for (int length = 0; (length = istrm.read(buffer)) != -1; )
                queue.add(new String(buffer, 0, length)); // store output in queue
                
        } catch (Exception e) { e.printStackTrace(); }
    }
}
疯狂程序员

至少有两个问题。

首先,关闭ScannerandPrintWriter也将关闭它们的不死流(在这种情况下Scanner是从标准输入读取的)。这是不可取的,因为,首先,您永远不想关闭 stdin 流,其次,该过程可能尚未完成对流的处理,但更重要的是,我会非常小心关闭不是您自己创建的流,只是说.

第二个问题是,您试图在SPQ实际有时间处理输出之前读取(流的)输出,例如,如果我调整您的代码并使用...

import java.io.IOException;
import java.io.InputStream;
import java.util.LinkedList;
import java.util.Queue;

public final class Main {
    public static void main(String[] args) throws IOException, InterruptedException {
        new Main();
    }

    public Main() throws IOException, InterruptedException {
        ProcessBuilder pb = new ProcessBuilder("bash", "-c", "ls");
        pb.redirectErrorStream(true);
        System.out.println(">> Start process");
        Process p = pb.start();
        Queue<String> stdout = new LinkedList<>();
        Thread thread = new Thread(new SPQ(p.getInputStream(), stdout));
        System.out.println(">> Start thread");
        thread.start();
        System.out.println(">> Waiting for process to exit");
        p.waitFor();
        System.out.println("<< Process has exited");
        System.out.println(stdout);
    }

    class SPQ implements Runnable {
        private Queue<String> queue;
        private InputStream istrm;

        public SPQ(InputStream istrm, Queue<String> queue) {
            this.istrm = istrm;
            this.queue = queue;
        }

        public void run() {
            System.out.println(">> Started reading stream");
            try {
                final byte[] buffer = new byte[1024];
                for (int length = 0; (length = istrm.read(buffer)) != -1;) {
                    queue.add(new String(buffer, 0, length)); // store output in queue
                }
            } catch (Exception e) {
                e.printStackTrace();
            }
            System.out.println("<< Done reading stream");
        }
    }
}

它会输出...

>> Start process
>> Start thread
>> Waiting for process to exit
<< Process has exited
>> Started reading stream
[]
<< Done reading stream

如您所见,我已经Queue在线程完成处理流之前打印了内容。

如果我在打印thread.join();后添加p.waitFor();...

>> Start process
>> Start thread
>> Waiting for process to exit
>> Started reading stream
<< Done reading stream
<< Process has exited
[contents
of
my
working
directory
which
is
not
very
interesting]

可运行的示例...

import java.io.IOException;
import java.io.InputStream;
import java.util.LinkedList;
import java.util.Queue;

public final class Main {
    public static void main(String[] args) throws IOException, InterruptedException {
        new Main();
    }

    public Main() throws IOException, InterruptedException {
        ProcessBuilder pb = new ProcessBuilder("bash", "-c", "ls");
        pb.redirectErrorStream(true);
        System.out.println(">> Start process");
        Process p = pb.start();
        Queue<String> stdout = new LinkedList<>();
        Thread thread = new Thread(new SPQ(p.getInputStream(), stdout));
        System.out.println(">> Start thread");
        thread.start();
        System.out.println(">> Waiting for process to exit");
        p.waitFor();
        thread.join();
        System.out.println("<< Process has exited");
        System.out.println(stdout);
    }

    class SPQ implements Runnable {
        private Queue<String> queue;
        private InputStream istrm;

        public SPQ(InputStream istrm, Queue<String> queue) {
            this.istrm = istrm;
            this.queue = queue;
        }

        public void run() {
            System.out.println(">> Started reading stream");
            try {
                final byte[] buffer = new byte[1024];
                for (int length = 0; (length = istrm.read(buffer)) != -1;) {
                    queue.add(new String(buffer, 0, length)); // store output in queue
                }
            } catch (Exception e) {
                e.printStackTrace();
            }
            System.out.println("<< Done reading stream");
        }
    }
}

请注意 - 我没有运行 Windows,所以我无法测试Powershell并且我已经完成了我能想到的最小示例,所以我没有将内容写入流,但从概念上讲,这解决了你似乎是的问题有

本文收集自互联网,转载请注明来源。

如有侵权,请联系[email protected] 删除。

编辑于
0

我来说两句

0条评论
登录后参与评论

相关文章

来自分类Dev

为什么UIWebView的AVPlayerViewController不在主线程上运行?

来自分类Dev

Kotlin:为什么 job.invokeOnCompletion() 块不在主线程上运行?

来自分类Dev

为什么要在主线程上订阅?

来自分类Dev

为什么CompletableFuture的thenAccept()无法在主线程上运行

来自分类Dev

为什么映像不会在主线程上加载?

来自分类Dev

为什么我的NSOperationQueue在主线程上运行?

来自分类Dev

为什么将UIViewController释放在主线程上?

来自分类Dev

为什么我的代码在主线程上运行?

来自分类Dev

为什么我在 Python 的主线程中看不到写入到子进程中的队列?

来自分类Dev

为什么不在主线程(Android)中执行所有操作?

来自分类Dev

为什么不在最低级别等待时主线程被保留?

来自分类Dev

为什么主线程不能比较其他线程更新的两个变量?

来自分类Java

为什么ForkJoinPool ::的invoke()阻塞主线程?

来自分类Java

为什么主线程不被终止

来自分类Java

为什么invokeLater的主线程中执行?

来自分类Java

为什么工作的AsyncTask主线程?

来自分类Dev

为什么Future会阻塞主线程?

来自分类Dev

为什么任务在主线程中运行?

来自分类Dev

无法在主线程上更新UI

来自分类Dev

调度到并发队列导致在主线程上执行?

来自分类Dev

GCD主队列和主线程有什么区别?

来自分类Dev

需要在主线程上执行什么

来自分类Dev

更改侦听端口不在Qt中的主线程上

来自分类Dev

如果不在主线程上,NSAttributedString initWithData和NSHTMLTextDocumentType崩溃

来自分类Dev

java.lang.IllegalStateException:不在主线程Google Maps上

来自分类Dev

为什么不在主线程上进行所有 CPU 密集型操作——使用协程?

来自分类Dev

为什么要在主线程上休眠才能运行Camel示例

来自分类Dev

为什么WPF的Dispatcher.Invoke在主线程上运行时不会导致死锁?

来自分类Dev

调度队列块主线程

Related 相关文章

  1. 1

    为什么UIWebView的AVPlayerViewController不在主线程上运行?

  2. 2

    Kotlin:为什么 job.invokeOnCompletion() 块不在主线程上运行?

  3. 3

    为什么要在主线程上订阅?

  4. 4

    为什么CompletableFuture的thenAccept()无法在主线程上运行

  5. 5

    为什么映像不会在主线程上加载?

  6. 6

    为什么我的NSOperationQueue在主线程上运行?

  7. 7

    为什么将UIViewController释放在主线程上?

  8. 8

    为什么我的代码在主线程上运行?

  9. 9

    为什么我在 Python 的主线程中看不到写入到子进程中的队列?

  10. 10

    为什么不在主线程(Android)中执行所有操作?

  11. 11

    为什么不在最低级别等待时主线程被保留?

  12. 12

    为什么主线程不能比较其他线程更新的两个变量?

  13. 13

    为什么ForkJoinPool ::的invoke()阻塞主线程?

  14. 14

    为什么主线程不被终止

  15. 15

    为什么invokeLater的主线程中执行?

  16. 16

    为什么工作的AsyncTask主线程?

  17. 17

    为什么Future会阻塞主线程?

  18. 18

    为什么任务在主线程中运行?

  19. 19

    无法在主线程上更新UI

  20. 20

    调度到并发队列导致在主线程上执行?

  21. 21

    GCD主队列和主线程有什么区别?

  22. 22

    需要在主线程上执行什么

  23. 23

    更改侦听端口不在Qt中的主线程上

  24. 24

    如果不在主线程上,NSAttributedString initWithData和NSHTMLTextDocumentType崩溃

  25. 25

    java.lang.IllegalStateException:不在主线程Google Maps上

  26. 26

    为什么不在主线程上进行所有 CPU 密集型操作——使用协程?

  27. 27

    为什么要在主线程上休眠才能运行Camel示例

  28. 28

    为什么WPF的Dispatcher.Invoke在主线程上运行时不会导致死锁?

  29. 29

    调度队列块主线程

热门标签

归档