Java Thread Safety

java.text.SimpleDateFormat is Not Thread Safe!!!

While working on some java code I noticed a Thread safety issue. I mentioned it to a colleague and quickly realized that maybe some people are not aware of the problem with java.text.SimpleDateFormat. If you look closely at the JavaDocs you will see a section entitled “Synchronization”. It basically says “Date formats are not synchronized” and “If multiple threads access a format concurrently, it must be synchronized externally”.

I see quite often code like the following in some utility class with methods throughout the application using it.

public static final SimpleDateFormat FORMAT = new SimpleDateFormat("dd/MM/yyyy");

Well this will not work in a multi-threaded application (Any Web application for example)

To prove this thread safety issue I wrote a simple program.

package mytest;

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Random;

public class TestDateFormat {
	public static void main(String[] args) throws Exception {

		final SimpleDateFormat dateFormat = new SimpleDateFormat("dd/MM/yyyy");

		final int numberOfThreads = 10;
		final int iterationsPerThread = 3000;

		final Thread[] threads = new Thread[numberOfThreads];

		for (int i = 0; i < numberOfThreads; i++) {
			Thread dateThread = new Thread() {
				public void run() {
					Random random = new Random();
					for (int j = 1; j <= iterationsPerThread; j++) {
						int day = random.nextInt(27) + 1;
						int month = random.nextInt(11) + 1;
						int year = random.nextInt(200) + 1800;

						String strDate ="" + day + "/" + month + "/" + year;
						try {
							Date myDate = dateFormat.parse(strDate);
							String parsedDate = dateFormat.format(myDate);
							Thread.sleep(1); //To help with the time-slicing
						} catch (Exception e) {
							throw new RuntimeException("Parse Exception Hit! Thread:" + Thread.currentThread().getName() + " Test String:" + strDate, e);
						}
					}
				}
			};
			threads[i] = dateThread;
			dateThread.start();
		}

		for (int i = 0; i < threads.length; i++) {
			threads[i].join();
		}

		System.out.println("Completed Successfully... " + numberOfThreads + " Threads. " + iterationsPerThread + " iterations per Thread.");

	}
}

When run this will spit out a bunch of parse exceptions that make no sense. Change the “numberOfThreads” to 1 and it magically works.

Beware of thread safety issues…
Kevin

It's only fair to share...
Share on FacebookGoogle+Tweet about this on TwitterShare on LinkedIn

Leave a Reply