SoFunction
Updated on 2025-03-06

Analysis of application scenario examples of ThreadLocal in Java

Speaking of thread safety, we can solve it through ThreadLocal. But as a powerful variable, its application scenarios are much more than that. In various frameworks, we can still use them to manage them. At the same time, you need to pay attention to memory leakage when using ThreadLocal. Let’s analyze these two points below and bring a display of the corresponding code.

1. Applications in various frameworks

In the transaction management of the Spring framework, ThreadLocal is used to manage connections. Each thread is a separate connection. When a transaction fails, it cannot affect the transaction process or results of other threads. There are also ORM frameworks and Mybatis that everyone has heard and witnessed, and the same is true for SqlSession.

//Spring TransactionSynchronizationManager class@Override
protected void doBegin(Object transaction, TransactionDefinition definition) {
  DataSourceTransactionObject txObject = (DataSourceTransactionObject) transaction;
  Connection con = null;
  try {
    //N lines of code are omitted here    if (()) {
      //Bind the database to connect to the thread(obtainDataSource(), ());
    }
  }
  catch (Throwable ex) {
    if (()) {
      //When an exception occurs, remove the connection in the thread      (con, obtainDataSource());
      (null, false);
    }
    throw new CannotCreateTransactionException("Could not open JDBC Connection for transaction", ex);
  }
}

2. Prevent memory leaks

Usually we operate ThreadLocal in the following way. After using threadlocal, we must remove it to prevent memory leakage.

private static final ThreadLocal<LoginUser> loginUserLocal = new ThreadLocal<LoginUser>();
public static LoginUser getLoginUser() {
  return ();
}
public static void setLoginUser(LoginUser loginUser) {
  (loginUser);
}
public static void clear() {
  ();
}
//Be sure to clean up after use to prevent memory leakagetry{
  (loginUser);
  //Execute other business logic}finally{
  ();
}

ThreadLocal instance extension in java:

/**
  * Date tool class (used ThreadLocal to get SimpleDateFormat, other methods can be copied directly to common-lang)
  * @author Niu Li
  * @date 2016/11/19
  */
public class DateUtil {

 private static Map<String,ThreadLocal<SimpleDateFormat>> sdfMap = new HashMap<String, ThreadLocal<SimpleDateFormat>>();

 private static Logger logger = ();

 public final static String MDHMSS = "MMddHHmmssSSS";
 public final static String YMDHMS = "yyyyMMddHHmmss";
 public final static String YMDHMS_ = "yyyy-MM-dd HH:mm:ss";
 public final static String YMD = "yyyyMMdd";
 public final static String YMD_ = "yyyy-MM-dd";
 public final static String HMS = "HHmmss";

 /**
   * Get the sdf instance of the corresponding thread according to the key in the map
   * @param pattern map key
   * @return This instance
   */
 private static SimpleDateFormat getSdf(final String pattern){
  ThreadLocal<SimpleDateFormat> sdfThread = (pattern);
  if (sdfThread == null){
   //Double inspection to prevent sdfMap from putting the value multiple times, the reason is the same as the double lock singleton.   synchronized (){
    sdfThread = (pattern);
    if (sdfThread == null){
     ("put new sdf of pattern " + pattern + " to map");
     sdfThread = new ThreadLocal<SimpleDateFormat>(){
      @Override
      protected SimpleDateFormat initialValue() {
       ("thread: " + () + " init pattern: " + pattern);
       return new SimpleDateFormat(pattern);
      }
     };
     (pattern,sdfThread);
    }
   }
  }
  return ();
 }

 /**
   * Parse the date according to the specified pattern
   * @param date The date to be parsed
   * @param pattern Specify the format
   * @return parsed date instance
   */
 public static Date parseDate(String date,String pattern){
  if(date == null) {
   throw new IllegalArgumentException("The date must not be null");
  }
  try {
   return getSdf(pattern).parse(date);
  } catch (ParseException e) {
   ();
   ("The parsed format is not supported:"+pattern);
  }
  return null;
 }
 /**
   * Format date according to the specified pattern
   * @param date The date to be formatted
   * @param pattern Specify the format
   * @return parsed format
   */
 public static String formatDate(Date date,String pattern){
  if (date == null){
   throw new IllegalArgumentException("The date must not be null");
  }else {
   return getSdf(pattern).format(date);
  }
 }
}

This is the article about the analysis of ThreadLocal application scenario examples in Java. For more detailed analysis of ThreadLocal application scenarios in Java, please search for my previous articles or continue browsing the related articles below. I hope everyone will support me in the future!