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



