【发布时间】:2015-09-10 12:28:23
【问题描述】:
我有兴趣使用java.util.Scanner。我正在阅读docs 并看到一行说A Scanner 在没有外部同步的情况下对于多线程使用是不安全的。我能否确认这意味着在两个单独线程中对两个单独文件进行操作的两个单独的 Scanner 对象可能会相互干扰?
谁能帮我在外部同步扫描器对象以用于安全线程操作?
【问题讨论】:
标签: java thread-safety java.util.scanner
我有兴趣使用java.util.Scanner。我正在阅读docs 并看到一行说A Scanner 在没有外部同步的情况下对于多线程使用是不安全的。我能否确认这意味着在两个单独线程中对两个单独文件进行操作的两个单独的 Scanner 对象可能会相互干扰?
谁能帮我在外部同步扫描器对象以用于安全线程操作?
【问题讨论】:
标签: java thread-safety java.util.scanner
如果您在两个线程中使用相同的 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”;这将是无用的。
我的同步建议是:
synchronised (this) { super.next (); }。但是不要用扫描仪尝试这个!有这么多的消费者方法,你不知道这个类是如何在内部实现的,所以你注定要失败!请参阅建议 1。nextInt()、nextDouble())或使用 has 方法(例如 @987654328),这将变得复杂@, hasNextDouble()),但没有第 2 点那么复杂。最后,我建议你看看第 1 点。
【讨论】:
我想在接受的答案中了解这一点。
如果您在两个线程中使用相同的 Scanner 实例,除非您同步对对象的访问,否则您将遇到麻烦。 但是两个独立的 Scanner 实例永远不会相互干扰。
实际上,如果两个独立的 Scanner 实例共享相同的输入源,它们可能相互干扰。考虑是否有两个 Scanner 对象包装 System.in 由两个不同的线程使用。当您在一个Scanner 上调用hasNextInt() 时,它将从System.in 提前读取足够的字符来确定存在一个有效整数。如果第一个线程没有调用nextInt(),那么第二个线程将无法读取预读字符。它们将位于第一个 Scanner 的内部缓冲区中。
实际上,一台扫描仪通过“窃取”字符来干扰另一台扫描仪。在同一流上有两个扫描仪是病态的。您的说法仅适用于不同输入流上的两个扫描仪。
【讨论】:
您可以毫无问题地使用来自多个线程的不同数据源的多个扫描仪。
将一个扫描仪与多个线程一起使用会导致问题。
【讨论】:
多线程使用是指两个线程对同一个对象进行操作。两个线程在两个不同的对象上运行是可以的。
【讨论】: