Usually applies to utility classes such as SimpleDateFormat
importjava.text.SimpleDateFormat;importjava.util.Date;importjava.util.concurrent.ExecutorService;importjava.util.concurrent.Executors;/** * Description: SimpleDateFormat is not thread safe. If multiple threads try to use it, then non thread-safe behaviors might occur (e.g. in this case, printing the same timestamp)
*/publicclassThreadLocalNormalUsage05 {publicstaticExecutorService threadPool =Executors.newFixedThreadPool(10);publicstaticvoidmain(String[] args) throwsInterruptedException {for (int i =0; i <1000; i++) {int finalI = i;threadPool.submit(newRunnable() { @Overridepublicvoidrun() {String date =newThreadLocalNormalUsage05().date(finalI);System.out.println(date); } }); }threadPool.shutdown(); }publicStringdate(int seconds) {// The unit for Date is ms, start counting from 1970.1.1 00:00:00 GMT Date date =newDate(1000* seconds);// Use thread local to get a thread safe DateFormat entity// SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");SimpleDateFormat dateFormat =ThreadSafeFormatter.dateFormatThreadLocal2.get();returndateFormat.format(date); }}classThreadSafeFormatter {publicstaticThreadLocal<SimpleDateFormat> dateFormatThreadLocal =newThreadLocal<SimpleDateFormat>() { @OverrideprotectedSimpleDateFormatinitialValue() {returnnewSimpleDateFormat("yyyy-MM-dd HH:mm:ss"); } };publicstaticThreadLocal<SimpleDateFormat> dateFormatThreadLocal2 =ThreadLocal.withInitial(() ->newSimpleDateFormat("yyyy-MM-dd HH:mm:ss"));}
Avoid to always pass parameters
Within the same thread, want to share a variable between different methods. Could use threadlocal to pass. E.g. UserId, tenantId
Other approaches:
Declare a static global variable: Not working because each request will have a different argument (e.g. userId, tenantId). The scope needs to be per request.
Use synchronized / concurrentHashmap (Thread->userId/tenantId mapping). Will have performance cost anyways.