Java交互式控制台

时间:2015-12-06 23:36:22

标签: java multithreading stdin

我目前正在开发Java命令行应用程序,我想让它成为交互式的。我的意思是,我有2个帖子:

  • 一个帖子永久性地将一些信息写入stdout
  • 第二个线程只从stdin读取并正在等待来自用户的一些命令

但关键是,当我在第一个线程向stdout写入内容时键入命令时,它真的很烦人,命令是" cut"。

例如: 我想输入命令'设置infolevel 2',当我输入时,第一个线程输出"一些信息1234"。

我的控制台输出可能如下所示:

set inf                  // user typing command into stdin
some information 1234    // first thread writes out information
olevel 2                 // continuing reading command from stdin

如果有人能告诉我是否有像这样的库/ API,那将是非常棒的。谢谢!

3 个答案:

答案 0 :(得分:1)

我猜你会使用System.out.println输出到控制台,new Scanner(System.in);用于读取输入。

基本上System.outPrintStreamSystem.inInputStream并且是不同的对象(和流)但它们都使用相同的来源(我猜IDE您的情况下的控制台或命令提示符)因此,当2个或更多线程尝试使用相同的源时,您将获得您提到的行为,因为默认情况下,主机环境或用户使用相同的源/控制台。请阅读以下Java source

<强>的System.out

  

/ **   *“标准”输入流。这个流已经存在   *打开并准备提供输入数据。通常这个流   *对应键盘输入或指定的其他输入源   *主机环境或用户。   * /

<强> System.in

  

/ **   *“标准”输出流。这个流已经存在   *打开并准备接受输出数据。通常这个流   *对应于显示输出或其他输出目的地   *由主机环境或用户指定。


据我所知,确实有没有这样的API 来帮助你找到你想要的东西,但是有很多选择的工作方法:

请注意,恕我直言选项3或基于同步的任何类似解决方案是您可能不想要的,因为它会限制您的输出功能

选项1:

配置其他控制台设备,然后使用System.console()访问它。在这种情况下,您将拥有不同的读取和写入控制台的来源,因此您将无法获得所看到的内容。如果您没有明确配置任何内容,那么默认情况下,System.console()NULL

选项2:

不是将输出写入控制台,而是使用文件来编写输出。这将确保您的输入和输出流不会相互混淆。

选项3:

如果读取和写入控制台的源都相同,则同步访问权限。下面是相同的代码,但请注意,在获取和释放对象锁定时,您仍然可以看到一些重叠但是在System.outSystem.in上获取或释放锁定后,您将看不到交叠。

public class Test {

    static Object object = new Object();

    public static void main(String[] args) {
        new Thread(){
            @Override
            public void run() {
                while(true){
                    try {
                        Thread.sleep(1000);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                    synchronized (object) {
                        Date date = new Date();
                        System.out.println("I am coming from first thread i.e. " + Thread.currentThread().getId() + " : " + date);
                    }
                }
            }
        }.start();

        new Thread(){
            @Override
            public void run() {
                Scanner scanner = new Scanner(System.in);
                while(true){
                    try {
                        Thread.sleep(1000);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                    synchronized (object) {
                        scanner.next();
                    }
                }
            }
        }.start();
    }

}

答案 1 :(得分:-1)

似乎你需要在某种对象上同步两个线程。类似于:private Object lockObject = new Object(); Thread t1 = new Thread() { public void run() {synchronized( lockObject ){ //your code } } };

答案 2 :(得分:-1)

您可以使用锁定作为他的答案中建议的svasa,或修改您的代码,以便您有一个执行输入和输出的线程,另一个线程执行计算工作。使用ArrayBlockingQueue将工作线程的输出发送到I / O线程。