У меня есть приведенный ниже код, который использует ThreadLocal для хранения отдельной копии SimpleDateFormat для каждого потока. Начальный шаблон у меня есть MM/dd/yyyy.
class PerThreadLocalVariables {
public static final ThreadLocal<SimpleDateFormat> THREAD_LOCAL_FORMATTER = ThreadLocal
.withInitial(() -> new SimpleDateFormat("MM/dd/yyyy"));
}
У меня есть следующая задача «TransactionService», которая использует экземпляр ThreadLocal для регистрации даты начала txn. Этот класс также имеет метод для изменения SimpleDateFormat для конкретной задачи —
class TransactionService implements Runnable {
@Override
public void run()
{
System.out.println(Thread.currentThread().getName() + ": startDate= "
+ PerThreadLocalVariables.THREAD_LOCAL_FORMATTER.get().format(new Date()));
try
{
Thread.sleep(10000);
System.out.println("After some time ... " + Thread.currentThread().getName() + ": date pattern= "
+ PerThreadLocalVariables.THREAD_LOCAL_FORMATTER.get().toPattern());
}
catch( InterruptedException e )
{
// TODO Auto-generated catch block
e.printStackTrace();
}
}
public void changeFormatterToYYYMMDD()
{
// Changing the thread local variable will not affect variable of other thread.
PerThreadLocalVariables.THREAD_LOCAL_FORMATTER.set(new SimpleDateFormat("yyyy/MM/dd"));
}
}
Теперь в основном методе я создаю три потока и запускаю их. Для первого потока (поток-1) я изменяю шаблон SimpleDateFormat на гггг/ММ/дд. Поэтому, согласно концепции ThreadLocal, изменение этого не должно влиять на шаблон, используемый двумя другими потоками (поток-2 и поток-3). Но проблема в том, что он даже не меняет шаблон для потока-1. Тем не менее я вижу исходный шаблон, т.е. MM/dd/yyyy. Я не уверен, что я делаю неправильно здесь-
public class ThreadLocalDemo {
public static void main( String[] args ) throws InterruptedException
{
TransactionService txn1 = new TransactionService();
new Thread(txn1, "thread-1").start();
Thread.sleep(2000);
new Thread(new TransactionService(), "thread-2").start();
Thread.sleep(5000);
new Thread(new TransactionService(), "thread-3").start();
txn1.changeFormatterToYYYMMDD(); // this will not affect thread-2 and thread-3's simpleDateFormat pattern
System.out.println("Changed SimpleDateFormat pattern to yyyy/MM/dd for thread-1");
}
}
вывод - (вы можете видеть, что шаблон для потока-1 тот же, то есть MM/dd/yyyy, он должен был измениться на yyyy/MM/dd согласно коду)
thread-1: startDate= 11/25/2019
thread-2: startDate= 11/25/2019
Changed SimpleDateFormat pattern to yyyy/MM/dd for thread-1
thread-3: startDate= 11/25/2019
After some time ... thread-1: date pattern= MM/dd/yyyy
After some time ... thread-2: date pattern= MM/dd/yyyy
After some time ... thread-3: date pattern= MM/dd/yyyy
SimpleDateFormat
известен своей проблемой и давно устарел. Не используйте его. ИспользуйтеLocalDate
иDateTimeFormatter
из java.time, современного API даты и времени Java. Они также являются потокобезопасными, поэтому нет необходимости в вашем локальном потоке. Один глобальныйDateTimeFormatter
подойдет при условии, что вы хотите, чтобы везде был один и тот же формат. - person Ole V.V.   schedule 25.11.2019