threadlocal 使用场景,threadlocal详细介绍

首页 > 技术 > 作者:YD1662023-04-15 23:45:51

threadlocal 使用场景,threadlocal详细介绍(1)

两大使用场景-ThreadLocal的用途

典型场景1: 每个线程需要一个独享的对象(通常是工具类,典型需要使用的类有SimpleDateFormat和Random)

典型场景2: 每个线程内需要保存全局变量(例如在拦截器中获取用户信息),可以让不同方法直接使用,避免参数传递的麻烦。

典型场景1:每个线程需要一个独享的对象

每个Thread内有自己的实例副本,不共享;

举例:SimpleDateFormat。(当多个线程共用这样一个SimpleDateFormat,但是这个类是不安全的)

packagethreadlocal; importjava.text.SimpleDateFormat; importjava.util.Date; importjava.util.concurrent.ExecutorService; importjava.util.concurrent.Executors; /** *描述:利用ThreadLocal,给每个线程分配自己的dateFormat对象,保证了线程安全,高效利用内存 */ publicclassThreadLocalNormalUsage05{ publicstaticExecutorServicethreadPool=Executors.newFixedThreadPool(10); publicstaticvoidmain(String[]args)throwsInterruptedException{ for(inti=0;i<1000;i ){ intfinalI=i; threadPool.submit(newRunnable(){ @Override publicvoidrun(){ Stringdate=newThreadLocalNormalUsage05().date(finalI); System.out.println(date); } }); } threadPool.shutdown(); } publicStringdate(intseconds){ //参数的单位是毫秒,从1970.1.100:00:00GMT计时 Datedate=newDate(1000*seconds); //SimpleDateFormatdateFormat=newSimpleDateFormat("yyyy-MM-ddHH:mm:ss"); SimpleDateFormatdateFormat=ThreadSafeFormatter.dateFormatThreadLocal2.get(); returndateFormat.format(date); } } classThreadSafeFormatter{ publicstaticThreadLocal<SimpleDateFormat>dateFormatThreadLocal=newThreadLocal<SimpleDateFormat>(){ @Override protectedSimpleDateFormatinitialValue(){ returnnewSimpleDateFormat("yyyy-MM-ddHH:mm:ss"); } }; publicstaticThreadLocal<SimpleDateFormat>dateFormatThreadLocal2=ThreadLocal .withInitial(()->newSimpleDateFormat("yyyy-MM-ddHH:mm:ss")); } 典型场景2:当前用户信息需要被线程内所有方法共享

每个线程内需要保存全局变量,可以让不同方法直接使用,避免参数传递的麻烦

packagethreadlocal; /** *描述:演示ThreadLocal用法2:避免传递参数的麻烦 */ publicclassThreadLocalNormalUsage06{ publicstaticvoidmain(String[]args){ newService1().process(""); } } classService1{ publicvoidprocess(Stringname){ Useruser=newUser("超哥"); UserContextHolder.holder.set(user); newService2().process(); } } classService2{ publicvoidprocess(){ Useruser=UserContextHolder.holder.get(); ThreadSafeFormatter.dateFormatThreadLocal.get(); System.out.println("Service2拿到用户名:" user.name); newService3().process(); } } classService3{ publicvoidprocess(){ Useruser=UserContextHolder.holder.get(); System.out.println("Service3拿到用户名:" user.name); UserContextHolder.holder.remove(); } } classUserContextHolder{ publicstaticThreadLocal<User>holder=newThreadLocal<>(); } classUser{ Stringname; publicUser(Stringname){ this.name=name; } }

注意点:

ThreadLocal方法使用总结场景一:initialValue

在ThreadLocal第一次get的时候把对象给初始化出来,对象的初始化时机可以由我们控制。

场景二:set

如果需要保存到ThreadLocal里面的对象的生成时机不由我们随意控制。例如拦截器生成的用户信息,用ThreadLocal.set直接放到ThreadLocal当中。

ThreadLocal原理

理清Thread,ThreadLocalMap以及ThreadLocal

threadlocal 使用场景,threadlocal详细介绍(2)

主要方法介绍

ThreadLocalMap发生冲突之后,会用线性探测法。另外,欢迎关注公众号Java笔记虾,后台回复“后端面试”,送你一份面试题宝典!

ThreadLocal使用问题内存泄露什么是内存泄露

某个对象不再有用,但是占用的内存却不能被回收。

Value的泄露

如何避免内存泄露呢?实际应用场景-在spring中的实例分析

栏目热文

文档排行

本站推荐

Copyright © 2018 - 2021 www.yd166.com., All Rights Reserved.