Java中的扫描器不是线程安全的吗? [英] Is the scanner in java not thread safe?

查看:65
本文介绍了Java中的扫描器不是线程安全的吗?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

I'm interested in using java.util.Scanner. I was reading the docs and saw a line saying A Scanner is not safe for multi threaded use without external synchronization. Can I confirm that this means that two separate Scanner objects in two separate threads operating on two separate files could interfere with each other?

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

Can anyone help me to synchronise scanner object externally to use for safe thread operation?

推荐答案

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

If you use the same instance of Scanner in two threads you will have trouble unless you synchronise access to the object. But two separate instances of Scanner will never interfere with each other.

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

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

First, are you really sure you need to synchronise at all? You can safely use different scanner instances in different threads without any danger. One thread can have
Scanner s1 = new Scanner (new File ("/tmp/file1.txt");
and another thread can have
Scanner s2 - new Scanner (new File ("/tmp/file2.txt"));
and there is no risk. The different scanners can use the same file, different files or completely different data sources. You still need to be cautious though. As noted by Stephen C below you will still get broken operation if two separate instances of Scanner are using the same stream or reader as their input then they will steal characters from each other. This warning applies to the constructors using InputStream, Readable and ReadableByteChannel.

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

The problem with using a single scanner in multiple threads is that it is sequentially consuming characters from a single source. If you have multiple threads consuming these characters in unsynchronised fashion then each thread will get some of the characters and none of the threads will get all of the characters. To illustrate: Imagine you have a scanner reading the string "qwertyuiop", and two separate threads each call function next() at the same time, then one thread might see "ertip" and the other thread would get "qwyuo"; which would be useless.

我对此进行同步的建议是:

My suggestions to synchronise this are:

  1. 不要多线程!为了使多线程应用程序稳定,可扩展且灵活,甚至肢体截肢也更可取!
  2. 有时,您可以将非线程安全类(或封装并委托)作为子类,并将对基类(或委托)的调用同步:synchronised (this) { super.next (); }.但是请不要使用Scanner尝试此操作!消费者方法太多了,您不知道该类是如何在内部实现的,所以注定要失败!请参阅建议1.
  3. 我在这里尝试做的是让一个线程运行Scanner,并将令牌馈入ArrayBlockingQueue.这样,您将获得完整的令牌,以正确的顺序进入队列.您可以根据需要从队列中读取任意数量的线程.但是请注意,除非小心处理满空条件,否则任何线程都可能被阻塞,无法读取或写入此队列.很有可能,无论您做什么,都将以永远无法完成的悬空线程结束.请参阅第1点.如果您有时要调用不同的 next 方法(例如nextInt()nextDouble())或使用 has 方法(例如hasNextDouble()),但不如第2点那么复杂.
  1. Do not multi-thread! Even amputation of body parts is preferrable to trying to make a multi-threaded application stable, scalable and flexible!
  2. Sometimes you can subclass a non-thread-safe class (or encapsulate and delegate) and synchronise calls to the base class (or delegate): synchronised (this) { super.next (); }. But don't try this with Scanner! There are so many consumer methods, and you have no idea how the class is implemented internally so you are doomed to fail! See suggestion 1.
  3. What I would try to do here is have a single thread running the Scanner and feeding the tokens into an ArrayBlockingQueue. That way you will get complete tokens going into the queue in their correct order. You can have as many threads as you like reading from the queue. But be aware that any of your threads can get blocked either reading or writing this queue unless you take care to handle full and empty conditions. Chances are that no matter what you do you will end up with dangling threads that never finish. See point 1. This will get complicated if you want to sometimes call different next methods (e.g. nextInt(), nextDouble()) or use the has methods (e.g. hasNextInt(), hasNextDouble()), but not as complicated as point 2.

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

Finally, I would suggest you see point 1.

这篇关于Java中的扫描器不是线程安全的吗?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆