TbDate isoDateFormat is ThreadLocal instead synchronization

This commit is contained in:
Sergey Matvienko 2023-07-18 20:24:31 +02:00
parent 235c6f94d9
commit 2a683f9977
2 changed files with 29 additions and 5 deletions

View File

@ -35,7 +35,8 @@ public class TbDate extends Date {
private static final DateTimeFormatter isoDateFormatter = DateTimeFormatter.ofPattern(
"yyyy-MM-dd[[ ]['T']HH:mm[:ss[.SSS]][ ][XXX][Z][z][VV][O]]").withZone(ZoneId.systemDefault());
private static final DateFormat isoDateFormat = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSSZ");
private static final ThreadLocal<DateFormat> isoDateFormat = ThreadLocal.withInitial(() ->
new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSSZ"));
public TbDate() {
super();
@ -73,9 +74,7 @@ public class TbDate extends Date {
}
public String toISOString() {
synchronized (TbDate.class) {
return isoDateFormat.format(this);
}
return isoDateFormat.get().format(this);
}
public String toLocaleString(String locale) {

View File

@ -25,6 +25,7 @@ import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.Test;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.List;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.ExecutionException;
@ -32,6 +33,8 @@ import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;
import static org.assertj.core.api.Assertions.assertThat;
@Slf4j
class TbDateTest {
@ -99,4 +102,26 @@ class TbDateTest {
future.get(30, TimeUnit.SECONDS);
}
}
@Test
void testToISOStringThreadLocalStaticFormatter() throws ExecutionException, InterruptedException, TimeoutException {
executor = MoreExecutors.listeningDecorator(Executors.newFixedThreadPool(1));
long ts = 1709217342987L; //Thu Feb 29 2024 14:35:42.987 GMT+0000
int offset = Calendar.getInstance().get(Calendar.ZONE_OFFSET); // for example 3600000 for GMT + 1
TbDate tbDate = new TbDate(ts - offset);
String datePrefix = "2024-02-29T14:35:42.987"; //without time zone
assertThat(tbDate.toISOString())
.as("format in main thread")
.startsWith(datePrefix);
assertThat(executor.submit(tbDate::toISOString).get(30, TimeUnit.SECONDS))
.as("format in executor thread")
.startsWith(datePrefix);
assertThat(new TbDate(ts - offset).toISOString())
.as("new instance format in main thread")
.startsWith(datePrefix);
assertThat(executor.submit(() -> new TbDate(ts - offset).toISOString()).get(30, TimeUnit.SECONDS))
.as("new instance format in executor thread")
.startsWith(datePrefix);
}
}