【问题标题】:Java Scanner next() methodJava 扫描器 next() 方法
【发布时间】:2017-10-21 21:11:27
【问题描述】:

这是来自Java的Scanner next()方法的解释:

此方法在等待输入扫描时可能会阻塞,即使一个 之前调用 hasNext() 返回 true。

如果调用 hasNext(),该方法如何等待用户输入?如果我们调用 hasNext() 并且它返回 true,我们知道有下一个标记,那么 next() 方法是如何以及为什么这样做的呢?

【问题讨论】:

    标签: java java.util.scanner


    【解决方案1】:

    您需要阅读方法的完整documentation

    从此扫描器中查找并返回下一个完整令牌。一个 完整的令牌之前和之后是匹配的输入 分隔符模式。此方法可能会在等待输入时阻塞 扫描,即使之前调用 hasNext() 返回 true。

    当有另一个令牌时,Scanner#hasNext 方法 (documentation) 可能会返回 true。但根据分隔符模式,令牌可能尚未被视为完成Scanner#next 将始终阻塞,直到令牌完成。

    如果Scanner 中有完整令牌,那么Scanner#next 将立即返回并且不会阻止


    您可以使用Scanner#useDelimiter 方法设置分隔符模式 (documentation)

    如果您没有设置特定的分隔符模式,Scanner 将使用匹配空白字符的默认模式。


    正如您所问的,blocked 意味着该方法等待并且直到所述事件发生才返回。

    考虑一下:

    System.out.println("Before");
    someBlockingMethod();
    System.out.println("After");
    

    public void someBlockingMethod() {
        // Sleep for a second (ignoring exceptions for simplicity)
        Thread.sleep(1000);
    }
    

    您只会在someBlockingMethod() 返回后看到After,并且只有在所述事件发生后才会发生这种情况。因此方法阻塞。在示例中,该方法会阻塞一秒钟。

    【讨论】:

    • 我不明白在读取控制台输入时会发生这种情况。你能提供一些示例代码吗?另外,这里的“阻止”实际上是什么意思?
    • 从控制台读取时,如果没有设置特定的分隔符模式,您可能不会遇到 hasNext truenext 阻塞的场景,因为您总是至少输入 使用控制台时输入信号结束(按enter换行)被Scanner视为空白字符 .
    • 当分隔符之间的输入很长时会发生这种情况吗?
    • 阻塞对我的程序有何影响?当我想使用这种方法时,这将如何影响我的编程逻辑?还是只是更慢?
    • 想想Scanner 连接到一个尚未完全可用的资源,例如Stream。如果 Stream 传递符号 Hell 但还不是 分隔符,如 空格行尾/流,那么你不需要不想将其用作令牌,因为一秒钟后o<whitespace> 来了。你想捕捉Hello 而不是Hello。在这种情况下,hasNext 返回true,但next 将阻塞并等待o<whitespace> 到来。
    【解决方案2】:

    Scanner#next 在到达 Scanner 使用的分隔符(空白是默认分隔符)或到达输入流的末尾之前不会返回字符串。

    如果hasNext返回true,则表示输入流中肯定还有更多数据,但可能仍需要阻塞,直到到达分隔符/EOF。

    【讨论】:

    • 我仍然不明白在读取控制台输入时会发生这种情况。另外,在这种情况下,“阻止”是什么意思,因为恐怕我理解错误。谢谢。
    • @LearningMath "Block" 表示等待。在硬件完成数据检索之前,线程上不会发生任何事情。
    【解决方案3】:

    如果你调试下面的代码,你会发现,实际上是 hasNext() 方法阻塞并等待用户输入:

    Scanner scanner = new Scanner(System.in);
    if (scanner.hasNext()) {
        String s = scanner.next();
    }
    

    那是因为 hasNext() 内部有一个阻塞步骤:

    public boolean hasNext() {
        ensureOpen();
        saveState();
        while (!sourceClosed) {
            if (hasTokenInBuffer())
                return revertState(true);
            readInput(); //THIS IS WAITING FOR USER INPUT
        }
    ...
    

    在控制台输入的情况下,hasNext() 等到输入完整的令牌并返回 true,然后后续的 next() 调用不会阻塞。

    在非控制台输入的情况下,即使没有完整的token,hasNext()也会返回true,后续的next()调用会阻塞并等待完整的token。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2016-01-15
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-05-09
      相关资源
      最近更新 更多