Recently I was asked by one of our team mate that during load testing, order creation was failing because of wrong inputs(One of the application I am working on is an Order Management Application) . However, the unit tests, with the same input was working fine. Investigation into it, led to (once again) an old jdk “designed” bug 4146524 (or feature). After seeing such issues in a number of applications, I am sure a number of developers are yet not aware of Format objects are not thread-safe. So if you create a Format object (or a MessageFormat, NumberFormat, DecimalFormat, ChoiceFormat, DateFormat or SimpleDateFormat object), it cannot be shared among threads.

A number of write ups are available on internet to make sure your Format objects can work on multi threaded environment. Recreating it below, if it can help some.

Thread unsafe implementation

package aminur.test.formatters;

import java.text.DecimalFormat;
import java.text.DecimalFormatSymbols;
import java.text.ParseException;

public final class ThreadUnsafePriceFormatter {
	// the price formats
	private static final DecimalFormat pointSeparatedFormat;

	static {
		DecimalFormatSymbols symbols = new DecimalFormatSymbols();
		symbols.setDecimalSeparator('.');
		pointSeparatedFormat = new DecimalFormat("#0.00", symbols);
	}
	private ThreadUnsafePriceFormatter() {
	}
	public static String formatPointSeparated(double price) {
		return pointSeparatedFormat.format(price);
	}
	public static Number parsePointSeparated(String price)
			throws ParseException {
		return pointSeparatedFormat.parse(price);
	}
}

Problem, In multi-threaded environment, it can throw exception.

private static void testThreadUnSafeFormatter() throws Exception {
		Callable<Number> task = new Callable<Number>() {
			public Number call() throws Exception {
				return ThreadUnsafePriceFormatter.parsePointSeparated("2.2");
			}
		};
		executeTasks(task);
}
private static void executeTasks(final Callable<Number> task)
			throws Exception {
		ExecutorService exec = Executors.newFixedThreadPool(100);
		List<Future<Number>> results = new ArrayList<Future<Number>>();
		for (int i = 0; i < 150; i++) {
			results.add(exec.submit(task));
		}

		exec.shutdown();

		for (Future<Number> result : results) {
			System.out.println(result.get());
		}
}

Thread safe implementation
I used the most recommended method ThreadLocal to provide a thread based copy of Format object.

package aminur.test.formatters;

import java.text.DecimalFormat;
import java.text.DecimalFormatSymbols;
import java.text.ParseException;

public class ThreadSafePriceFormatter {
	// the price formats
	private static final ThreadLocal<DecimalFormat> pointSeparatedFormat = new ThreadLocal<DecimalFormat>() {
		@Override
		protected DecimalFormat initialValue() {
			DecimalFormatSymbols symbols = new DecimalFormatSymbols();
			symbols.setDecimalSeparator('.');
			return (new DecimalFormat("#0.00", symbols));
		}
	};
	private ThreadSafePriceFormatter() {
	}
	public static String formatPointSeparated(double price) {
		return pointSeparatedFormat.get().format(price);
	}
	public static Number parsePointSeparated(String price)
			throws ParseException {
		return pointSeparatedFormat.get().parse(price);
	}
}

Java Specialist,  Dr. Heinz M. Kabutz suggests using ThreadLocal with SoftReference. Some have also suggested to use Joda-Time