温馨提示×

温馨提示×

您好,登录后才能下订单哦!

密码登录×
登录注册×
其他方式登录
点击 登录注册 即表示同意《亿速云用户服务条款》

如何在java中使用ThreadLocal

发布时间:2021-02-18 14:26:42 来源:亿速云 阅读:245 作者:Leah 栏目:开发技术

这篇文章给大家介绍如何在java中使用ThreadLocal,内容非常详细,感兴趣的小伙伴们可以参考借鉴,希望对大家能有所帮助。

1、各种框架中的应用

Spring框架的事务管理中使用ThreadLocal来管理连接,每个线程是单独的连接,当事务失败时不能影响到其他线程的事务过程或结果,还有大家耳闻目睹的ORM框架、Mybatis也是用ThreadLocal管理,SqlSession也是如此。

//Spring TransactionSynchronizationManager类 @Override protected void doBegin(Object transaction, TransactionDefinition definition) {   DataSourceTransactionObject txObject = (DataSourceTransactionObject) transaction;   Connection con = null;   try {     //此处省略N行代码     if (txObject.isNewConnectionHolder()) {       //绑定数据库连接到线程中 TransactionSynchronizationManager.bindResource(obtainDataSource(), txObject.getConnectionHolder());     }   }   catch (Throwable ex) {     if (txObject.isNewConnectionHolder()) {       //当发生异常时,移除线程中的连接       DataSourceUtils.releaseConnection(con, obtainDataSource());       txObject.setConnectionHolder(null, false);     }     throw new CannotCreateTransactionException("Could not open JDBC Connection for transaction", ex);   } }

2、防止内存泄漏

通常我们是使用如下的方式操作ThreadLocal,在使用完threadlocal后一定要remove掉,防止内存泄露。

private static final ThreadLocal<LoginUser> loginUserLocal = new ThreadLocal<LoginUser>(); public static LoginUser getLoginUser() {   return loginUserLocal.get(); } public static void setLoginUser(LoginUser loginUser) {   loginUserLocal.set(loginUser); } public static void clear() {   loginUserLocal.remove(); } //在使用完后一定要清理防止内存泄露 try{   loginUserLocal.set(loginUser);   //执行其他业务逻辑 }finally{   loginUserLocal.remove(); }

java中ThreadLocal实例扩展:

public class DateUtil {  private static Map<String,ThreadLocal<SimpleDateFormat>> sdfMap = new HashMap<String, ThreadLocal<SimpleDateFormat>>();  private static Logger logger = LoggerFactory.getLogger(DateUtil.class);  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";  /**   * 根据map中的key得到对应线程的sdf实例   * @param pattern map中的key   * @return 该实例   */  private static SimpleDateFormat getSdf(final String pattern){   ThreadLocal<SimpleDateFormat> sdfThread = sdfMap.get(pattern);   if (sdfThread == null){    //双重检验,防止sdfMap被多次put进去值,和双重锁单例原因是一样的    synchronized (DateUtil.class){     sdfThread = sdfMap.get(pattern);     if (sdfThread == null){      logger.debug("put new sdf of pattern " + pattern + " to map");      sdfThread = new ThreadLocal<SimpleDateFormat>(){       @Override       protected SimpleDateFormat initialValue() {        logger.debug("thread: " + Thread.currentThread() + " init pattern: " + pattern);        return new SimpleDateFormat(pattern);       }      };      sdfMap.put(pattern,sdfThread);     }    }   }   return sdfThread.get();  }  /**   * 按照指定pattern解析日期   * @param date 要解析的date   * @param pattern 指定格式   * @return 解析后date实例   */  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) {    e.printStackTrace();    logger.error("解析的格式不支持:"+pattern);   }   return null;  }  /**   * 按照指定pattern格式化日期   * @param date 要格式化的date   * @param pattern 指定格式   * @return 解析后格式   */  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);   }  } }

关于如何在java中使用ThreadLocal就分享到这里了,希望以上内容可以对大家有一定的帮助,可以学到更多知识。如果觉得文章不错,可以把它分享出去让更多的人看到。

向AI问一下细节

免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。

AI