Reputation: 65
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?
Upvotes: 4
Views: 4846
Reputation: 634
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.
edit in response to comment asking how to synchronise
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.
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:
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.nextInt()
, nextDouble()
) or use the has methods (e.g. hasNextInt()
, hasNextDouble()
), but not as complicated as point 2.Finally, I would suggest you see point 1.
Upvotes: 2
Reputation: 718826
I want to pick up on this point in the accepted answer.
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.
Actually, two separate Scanner
instances can interfere with each other if they share the same input source. Consider if you have two Scanner objects wrapping System.in
used by two distinct threads. When you call hasNextInt()
on one Scanner
, it will read ahead from System.in
enough characters to determine that there is a valid integer. If the first thread then didn't call nextInt()
, the second thread would not be able to read the read-ahead characters. They will be sitting in the internal buffers of the first Scanner
.
In effect, one Scanner is interfering with the other by "stealing" characters. Having two Scanners on the same stream is pathological. Your statement is only true for two Scanners on different input streams.
Upvotes: 1
Reputation: 6716
You can use multiple scanners using different data sources from multiple threads without problems.
Using one scanner with multiple threads will lead to problems.
Upvotes: 0
Reputation: 4080
Multi threaded use refers to two threads operating on the same object. Two threads operating on two different objects is fine.
Upvotes: 0