【问题标题】:Is the scanner in java not thread safe?java中的扫描仪不是线程安全的吗?
【发布时间】:2015-09-10 12:28:23
【问题描述】:

我有兴趣使用java.util.Scanner。我正在阅读docs 并看到一行说A Scanner 在没有外部同步的情况下对于多线程使用是不安全的。我能否确认这意味着在两个单独线程中对两个单独文件进行操作的两个单独的 Scanner 对象可能会相互干扰?

谁能帮我在外部同步扫描器对象以用于安全线程操作?

【问题讨论】:

    标签: java thread-safety java.util.scanner


    【解决方案1】:

    如果您在两个线程中使用相同的 Scanner 实例,除非您同步对对象的访问,否则您将遇到麻烦。但是两个独立的 Scanner 实例永远不会相互干扰。

    编辑以回应询问如何同步的评论

    首先,您确定需要同步吗?您可以在不同的线程中安全地使用不同的扫描程序实例,而不会产生任何危险。一个线程可以有
    Scanner s1 = new Scanner (new File ("/tmp/file1.txt");
    另一个线程可以有
    Scanner s2 - new Scanner (new File ("/tmp/file2.txt"));
    并且没有风险。不同的扫描仪可以使用相同的文件、不同的文件或完全不同的数据源。不过,您仍然需要谨慎。正如 Stephen C below 所指出的,如果两个单独的 Scanner 实例使用相同的流或读取器作为其输入,那么它们将彼此窃取字符,您仍然会遇到操作中断。此警告适用于使用 InputStream、Readable 和 ReadableByteChannel 的构造函数。

    在多个线程中使用单个扫描器的问题在于它会按顺序使用来自单个源的字符。如果您有多个线程以不同步的方式使用这些字符,那么每个线程将获得一些字符,并且没有一个线程将获得所有字符。举例说明:假设您有一个扫描仪读取字符串“qwertyuiop”,并且两个单独的线程同时调用函数next(),那么一个线程可能会看到“ertip”而另一个线程会得到“qwyuo”;这将是无用的。

    我的同步建议是:

    1. 不要多线程!即使是截肢身体部位也比试图使多线程应用程序稳定、可扩展和灵活更可取!
    2. 有时您可以子类化非线程安全类(或封装和委托)并同步对基类(或委托)的调用:synchronised (this) { super.next (); }。但是不要用扫描仪尝试这个!有这么多的消费者方法,你不知道这个类是如何在内部实现的,所以你注定要失败!请参阅建议 1。
    3. 我在这里尝试做的是让一个线程运行扫描程序并将令牌提供给 ArrayBlockingQueue。这样,您将获得完整的令牌以正确的顺序进入队列。您可以从队列中读取任意数量的线程。但是请注意,除非您注意处理满和空的情况,否则您的任何线程都可能在读取或写入此队列时被阻塞。很有可能,无论你做什么,你最终都会得到永远不会结束的悬空线程。请参阅第 1 点。如果您有时想调用不同的 next 方法(例如 nextInt()nextDouble())或使用 has 方法(例如 @987654328),这将变得复杂@, hasNextDouble()),但没有第 2 点那么复杂。

    最后,我建议你看看第 1 点。

    【讨论】:

    • 能否指定如何在外部同步扫描器对象以用于安全线程操作?
    【解决方案2】:

    我想在接受的答案中了解这一点。

    如果您在两个线程中使用相同的 Scanner 实例,除非您同步对对象的访问,否则您将遇到麻烦。 但是两个独立的 Scanner 实例永远不会相互干扰。

    实际上,如果两个独立的 Scanner 实例共享相同的输入源,它们可能相互干扰。考虑是否有两个 Scanner 对象包装 System.in 由两个不同的线程使用。当您在一个Scanner 上调用hasNextInt() 时,它将从System.in 提前读取足够的字符来确定存在一个有效整数。如果第一个线程没有调用nextInt(),那么第二个线程将无法读取预读字符。它们将位于第一个 Scanner 的内部缓冲区中。

    实际上,一台扫描仪通过“窃取”字符来干扰另一台扫描仪。在同一流上有两个扫描仪是病态的。您的说法仅适用于不同输入流上的两个扫描仪。

    【讨论】:

      【解决方案3】:

      您可以毫无问题地使用来自多个线程的不同数据源的多个扫描仪。

      一个扫描仪多个线程一起使用会导致问题。

      【讨论】:

        【解决方案4】:

        多线程使用是指两个线程对同一个对象进行操作。两个线程在两个不同的对象上运行是可以的。

        【讨论】:

          猜你喜欢
          • 2019-10-22
          • 2017-09-13
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2011-03-07
          • 1970-01-01
          • 1970-01-01
          • 2013-11-15
          相关资源
          最近更新 更多