java - java中的扫描器不是线程安全的吗?

标签 java thread-safety java.util.scanner

我对使用 java.util.Scanner 很感兴趣。我正在阅读 docs并看到一行说 A Scanner is not safe for multi threaded use without external synchronization。我可以确认这意味着在两个独立文件上运行的两个独立线程中的两个独立 Scanner 对象可能会相互干扰吗?

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

最佳答案

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

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

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

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

我的同步建议是:

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

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

关于java - java中的扫描器不是线程安全的吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/31024254/

相关文章:

Java Scanner .nextInt() 跳过输入

java - 在Java中从扫描仪读取可变宽度标记?

java - Junit testing in play with java.lang.OutOfMemoryError 已被捕获,Java 堆空间

c# - 其他对象引发的工作事件时的跨线程操作

java - 如何逐行解析一个巨大的文件,高效地序列化和反序列化一个巨大的对象?

python - GAE/P存储SES连接和线程安全

c - Del. and r/w linked List Nodes in Multithreading with RW-locks -> 死锁?

Java - 解析文本文件 - 扫描仪、阅读器或其他?

java - 使用 PBKDF2WithHmacSHA512 的密码保护在生产设置 (AWS) 上花费了大量的处理时间

java - Java中实参和形参的区别