RUKMANI SELVARAJ
RUKMANI SELVARAJ

Reputation: 65

Is the scanner in java not thread safe?

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

Answers (4)

Terrible Tadpole
Terrible Tadpole

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:

  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.

Finally, I would suggest you see point 1.

Upvotes: 2

Stephen C
Stephen C

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

Nitram
Nitram

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

phil_20686
phil_20686

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

Related Questions