当前位置: 首页 > 面试题库 >

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

张鹏云
2023-03-14
问题内容

我对使用感兴趣java.util.Scanner。我在阅读文档时看到一行内容,即如果没有外部同步,扫描程序对于多线程使用来说是不安全的。我是否可以确认这意味着在两个单独的文件上运行的两个单独的线程中的两个单独的Scanner对象可能会相互干扰?

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


问题答案:

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

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

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


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

我的同步建议是:

  1. 不要多线程!甚至肢体截肢也比试图使多线程应用程序稳定,可扩展和灵活更可取!
  2. 有时候,你也可以继承一个非线程安全类(或封装和委托)和同步调用基类(或代表): synchronised (this) { super.next (); }。但是,请勿尝试使用Scanner!消费者方法太多了,您不知道该类是如何在内部实现的,所以注定要失败!见建议1。
  3. 我在这里尝试做的是让一个线程运行Scanner,并将令牌馈入ArrayBlockingQueue。这样,您将获得完整的令牌,以正确的顺序进入队列。您可以从队列中读取任意多个线程。但是请注意,除非小心处理满空条件,否则任何线程都可能会被阻塞,无法读取或写入此队列。很有可能,无论您做什么,都将以永远无法完成的悬空线程结束。看点1,这将让复杂,如果你想打电话,有时不同的 下一个 方法(例如nextInt()nextDouble()),或使用 方法(例如hasNextInt()hasNextDouble()),但不是那样复杂点2。

最后,我建议您看一下第1点。



 类似资料:
  • 问题内容: 在我的Java项目中,我需要以多种方式使用TreeMap。我发现ConcurrentSkipListMap是我需要的,但是某些方法不是线程安全的。其中之一- containsKey(Object key)。以多种方式使用此方法的典型解决方案是什么?在我的程序中,我需要放置不会替换旧密钥的密钥,如果不可能的话,我将放置另一个密钥而不会获得唯一密钥。因为我不会丢失信息,所以应该使用哪种构造

  • 问题内容: Java线程安全性易变吗?也就是说,可以安全地读取和写入它而无需锁定吗? 问题答案: 是的,您可以从中读取并安全地对其进行写入-但您不能做任何复合操作,例如安全地对其进行递增,因为这是一个读/修改/写周期。还有一个问题是它如何与 其他 变量的访问交互。 坦率地说,volatile的确切性质令人困惑(有关更多详细信息,请参见JLS的内存模型部分)-我 个人 通常会使用它作为确保正确使用的

  • 在我的应用程序中,我使用多个线程来处理客户端连接。 我在调试时发现了一个非常奇怪的行为——我有一个SelectionKey,通过调用(使用调试器)它的interestTops()方法,返回值是1(READ),但当我将数据发送到与该键对应的套接字时,选择器不会被唤醒。。 如果使用调试器,我将特定选择键更改为1(即使是1),选择器会突然对该更改做出反应。 在给定的时间内,我只有一个线程处理一个连接,但

  • 问题内容: 我知道Struts2 Action类是线程安全的,因为这些操作放在了值堆栈中。值堆栈又是动作上下文的一部分。由于操作上下文是线程本地的,因此存储在操作上下文中的值(包括值堆栈)在每个线程中都是唯一的。因此,动作是线程安全的。 但是考虑一下拦截器:它们确实很有用,它们为程序员完成了所有繁琐的小工作……例如验证,获取参数值等。但是要考虑的是:拦截器可以在多个请求之间共享。那么这会使拦截器线

  • 我找到了关于线程安全的代码,但它没有来自给出示例的人的任何解释。我想知道为什么如果我不在“count”之前设置“synchronized”变量,那么count值将是非原子的(总是=200是期望的结果)。谢谢

  • 问题内容: 我有一个多线程程序,在其中创建生成器函数,然后将其传递给新线程。我希望它本质上是共享/全局的,以便每个线程都可以从生成器获取下一个值。 使用这样的生成器是否安全?还是会遇到从多个线程访问共享生成器的问题/情况? 如果不是,是否有更好的方法来解决此问题?我需要可以在列表中循环并为任何线程调用它生成下一个值的东西。 问题答案: 它不是线程安全的;同时调用可能交错,并与局部变量混淆。 常用的