Use stream to verify that SimpleDateFormat is thread unsafe

Introduction

Hello. It's Kecho. ** Do you guys use SimpleDateFormat and stream? ** ** It's a niche. I love stream. This time we will verify that SimpleDateFormat is thread unsafe.

Preparation

First, prepare a Date type object.

SimpleDateFormat sdf = new SimpleDateFormat("yyyy/MM/dd hh:mm:ss");

Calendar day1 = Calendar.getInstance();
day1.set(2020, 0, 31, 0, 0, 0);
Calendar day2 = Calendar.getInstance();
day2.set(1995, 3, 6, 0, 0, 0);

Let's put it in the list.

for (int i = 0; i < 10; i++) {
	//Fill the list with 20 Date objects
	list.add(day1.getTime());
	list.add(day2.getTime());
}

First, process without executing in parallel.

list.stream().map(date -> sdf.format(date)).forEach(System.out::println);
//Convert each element to String in turn and output

The whole picture is below.

SimpleDateFormat sdf = new SimpleDateFormat("yyyy/MM/dd hh:mm:ss");

Calendar day1 = Calendar.getInstance();
day1.set(2020, 0, 31, 0, 0, 0);
Calendar day2 = Calendar.getInstance();
day2.set(1995, 3, 6, 0, 0, 0);
List<Date> list = new ArrayList<>(); //Creating a list

for (int i = 0; i < 10; i++) {
	//Fill the list with Date objects
	list.add(day1.getTime());
	list.add(day2.getTime());
}

list.stream().map(date -> sdf.format(date)).forEach(System.out::println);

Run in single thread

2020/01/31 12:00:00
1995/04/06 12:00:00
2020/01/31 12:00:00
1995/04/06 12:00:00
2020/01/31 12:00:00
1995/04/06 12:00:00
2020/01/31 12:00:00
1995/04/06 12:00:00
2020/01/31 12:00:00
1995/04/06 12:00:00
2020/01/31 12:00:00
1995/04/06 12:00:00
2020/01/31 12:00:00
1995/04/06 12:00:00
2020/01/31 12:00:00
1995/04/06 12:00:00
2020/01/31 12:00:00
1995/04/06 12:00:00
2020/01/31 12:00:00
1995/04/06 12:00:00

There seems to be no problem.

Run in multiple threads

stream will do parallel processing just by adding parallel () to the intermediate operation.

list.stream().map(date -> sdf.format(date)).forEach(System.out::println);

Let's do it!

2020/01/31 12:00:00
1995/01/31 12:00:00 //what's this
1995/04/06 12:00:00
2020/01/31 12:00:00
2020/01/31 12:00:00
2020/01/31 12:00:00
2020/01/31 12:00:00
1995/04/06 12:00:00
1995/04/06 12:00:00
2020/01/31 12:00:00
1995/04/06 12:00:00
2020/01/31 12:00:00
1995/04/06 12:00:00
2020/01/31 12:00:00
1995/04/06 12:00:00
1995/04/06 12:00:00
2020/01/31 12:00:00
1995/04/06 12:00:00
2020/01/31 12:00:00
1995/04/31 12:00:00 //what's this

Some unexpected dates were output. I was able to confirm that it is thread unsafe.

Countermeasures

You may create a SimpleDateFormat object in each thread. Basically, it is better to use the Date And Time API implemented from Java 8.

Implementation using DateTimeFormatter

DateTimeFormatter dtf = DateTimeFormatter.ofPattern("yyyy/MM/dd hh:mm:ss");

LocalDateTime today = LocalDateTime.now();
LocalDateTime birthDay = LocalDateTime.of(1995, 4, 6, 12, 0, 0);

List<LocalDateTime> list = new ArrayList<>();

for (int i = 0; i < 10; i++) {
	//Fill the list with Date objects
	list.add(today);
	list.add(birthDay);
}

list.stream().parallel().map(date -> dtf.format(date)).forEach(System.out::println);
2020/01/31 09:33:20
1995/04/06 12:00:00
1995/04/06 12:00:00
2020/01/31 09:33:20
1995/04/06 12:00:00
2020/01/31 09:33:20
2020/01/31 09:33:20
2020/01/31 09:33:20
2020/01/31 09:33:20
2020/01/31 09:33:20
2020/01/31 09:33:20
1995/04/06 12:00:00
1995/04/06 12:00:00
1995/04/06 12:00:00
1995/04/06 12:00:00
1995/04/06 12:00:00
2020/01/31 09:33:20
2020/01/31 09:33:20
1995/04/06 12:00:00
1995/04/06 12:00:00

Sounds okay.

Summary

Use Date And Time API for Java 8 and above

Recommended Posts

Use stream to verify that SimpleDateFormat is thread unsafe
SimpleDateFormat is thread unsafe
Use cryptographically secure pseudo-random numbers to verify that the solution to the Monty Hall problem is not 50%
Function is very easy to use
"Let's write versatile code that is easy to use over time" (nth time)
Write code that is difficult to test
[Rails] Enum is easier to use! Enumelize!
Code that is difficult to debug and parse
Write code that is easy to maintain (Part 1)
Write code that is easy to maintain (Part 4)
Write code that is easy to maintain (Part 3)