【发布时间】:2019-11-25 11:18:13
【问题描述】:
我有下面给出的代码,它使用 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"));
}
}
现在在 main 方法中,我创建三个线程并启动它们,对于第一个线程(线程 1),我将 SimpleDateFormat 模式更改为 yyyy/MM/dd。因此,根据 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类是出了名的麻烦和过时。不要使用它。使用现代 Java 日期和时间 API java.time 中的LocalDate和DateTimeFormatter。它们是 akso 线程安全的,因此不需要您的线程本地。一个全局的DateTimeFormatter就可以了,前提是您希望在所有地方都使用相同的格式。
标签: java multithreading simpledateformat thread-local