【问题标题】:Reading from standard input using java.io.InputStreamReader hangs when process runs in background当进程在后台运行时,使用 java.io.InputStreamReader 从标准输入中读取会挂起
【发布时间】:2013-08-22 15:05:28
【问题描述】:

我正在编写一个具有多个线程的 Java 程序。其中一个线程负责从标准输入中读取行并对其进行解析。

正常运行时一切正常,但是当程序在后台运行时(在 Linux 中)使用:

$ java -jar my_jar_file &

我的程序挂起(至少在进入前台之前)。

在后台运行时,我真的不需要标准输入,但我也不希望我的程序挂起。

我搜索了一种以编程方式确定进程是否在后台运行但找不到的方法。

这是从标准输入读取的代码:

InputStreamReader inputStreamReader = new InputStreamReader(System.in);
BufferedReader br = new BufferedReader(inputStreamReader);

String line = null;

try {
  while ((line = br.readLine()) != null) {
    parseInputLine(line, br);
  }
} catch (IOException e) {
  // TODO Auto-generated catch block
  e.printStackTrace();
}

据我所知,程序在到达br.readLine() 命令时会挂起。

【问题讨论】:

  • 在后台运行程序时从标准输入读取是没有意义的。
  • 是的,用于某些读/写操作的标准 I/O 块。如果你希望它是非阻塞的,你应该使用 NIO。
  • 我完全同意,这就是为什么我试图找到一种方法来检测我在后台运行,然后甚至不尝试从 STDIN 读取
  • Josh - 什么是“NIO”?
  • @Ari 新输入/输出。比较两者的文章可以找到here

标签: java


【解决方案1】:

我猜读者正在等待输入,您可能可以从命令行输入您的输入

【讨论】:

  • 问题是为什么这会阻塞整个程序并且不让其他线程正常运行(当进程处于前台时它工作正常)。
【解决方案2】:

readLine 是一个阻塞调用。所以它显然是在等待输入。如果您希望它在后台运行,请从这样的文件中向其传递输入

java TakeInput < test.txt &

这里的类如下,test.txt 也如下所示:

public class TakeInput
{
    public static void main(String[] args)
    {
        InputStreamReader inputStreamReader = new InputStreamReader(System.in);
        BufferedReader br = new BufferedReader(inputStreamReader);

        String line = null;

        try {
          while ((line = br.readLine()) != null) {
              System.out.println(line);
          }
        } catch (IOException e) {
          // TODO Auto-generated catch block
          e.printStackTrace();
        }
    }
}

写一个文本文件为 test.txt 有说

test1
test2
test3

【讨论】:

  • 我知道 readLine 是阻塞的,这就是为什么我有一个专门的线程。我试图理解的问题是为什么其他(完全不相关的)线程在后台运行时会挂起(在前台时一切正常)
  • 使用&lt;$- 可以解决问题(即我的程序能够在后台运行而不会卡住),但这仍然意味着我需要明确地“帮助”它理解它在后台运行更改命令(与使用 &lt; /dev/null 相同)。我真正想要的是一种自动完成的方法。
【解决方案3】:

我不相信 Java 程序可以确定它是在前台运行还是在后台运行。

我试过System.console(),结果如下:

  • Linux - 如果标准输入从文件重定向,则返回 null,与前台/后台状态无关
  • Windows - 同样的事情;
  • Cygwin - 似乎总是返回 null

我怀疑你需要从命令行调用程序

java -cp ... ClassName < /dev/null

【讨论】:

    【解决方案4】:

    尝试使用 .ready() 函数。

    try {
          if (stdError.ready()) 
          {
                while((line= stdError.readLine()) != null){
                    logger.error(line);
                }
          }
    }
    

    对标准输出做同样的事情。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2019-01-07
      • 1970-01-01
      • 1970-01-01
      • 2015-03-04
      • 2015-08-19
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多