典型场景一:

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

代码示例:

public class ThreadLocalNormalUsage05 {public static ExecutorService threadPool = Executors.newFixedThreadPool(10);public static void main(String[] args) {for (int i = 0; i < 1000; i++) {int finalI = i;threadPool.submit(new Runnable() {@Overridepublic void run() {String date = new ThreadLocalNormalUsage05().date(finalI);System.out.println(date);}});}}public String date(int secods) {Date date = new Date(1000 * secods);SimpleDateFormat dateFormat = ThreadSafeFormatter.dateFormatThreadLocal.get();return dateFormat.format(date);}
}class ThreadSafeFormatter {public static ThreadLocal<SimpleDateFormat> dateFormatThreadLocal = new ThreadLocal<SimpleDateFormat>(){@Overrideprotected SimpleDateFormat initialValue() {return new SimpleDateFormat("yyyy-MM-dd hh:mm:ss");}};
}

典型场景二:

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

这些信息在同一个线程内相同,但是在不同的线程内是不同的,所以不能使用 static 方法来解决。使用 ConcurrentHashMap,synchronized 等会对性能有影响。

代码示例:


public class ThreadLocalNormalUsage06 {public static void main(String[] args) {new Service1().process();}
}class Service1 {public void process() {User user = new User("小张");UserContextHolder.holder.set(user);new Service2().process();}
}class Service2 {public void process() {User user = UserContextHolder.holder.get();System.out.println("service2" + user.name);new Service3().process();}
}class Service3 {public void process() {User user = UserContextHolder.holder.get();System.out.println("service3" + user.name);UserContextHolder.holder.remove();}
}class UserContextHolder {public static ThreadLocal<User> holder = new ThreadLocal<>();
}class User {String name;public User(String name) {this.name = name;}
}

总结

ThreadLocal 有 set 和 initialValue 两种方法保存对象,当我们能够控制对象初始化时机的时候可以用 initialValue。当我们控制不了,需要某些条件触发的时候可用 set。

使用 ThreadLocal 的四点好处:

  • 线程安全
  • 不需要加锁,提高执行效率
  • 高效使用内存(对象生成),节省开销。
  • 免去传参的麻烦,如场景二。

每一个线程都有一个 ThreadLocalMap,这里面存放的是 ThreadLocal,如果在使用线程池的环境下,不停的向 ThreadLocalMap 中新增 ThreadLocal,那么极有可能引发内存泄露,所以在最后调用完的时候需要记得删除ThreadLocal。如 Service3 中的示例。

ThreadLocal的两种用法相关推荐

  1. ThreadLocal的两种用法总结

    ThreadLocal的作用 ThreadLocal是一个线程内部的数据存储类,通过它可以在指定的线程中存储数据,数据存储以后,只有在指定的线程中可以获取到存储的数据,对于其他线程来说则无法取到数据. ...

  2. C++ operator两种用法【转】

    C++中的operator,有两种用法,一种是operator overloading(操作符重载),一种是operator casting(操作隐式转换).下面分别进行介绍: 1.operator ...

  3. html如何让a标签提交表单提交,html post请求之a标签的两种用法解析

    这篇文章主要介绍了html post请求之a标签的两种用法,本文通过实例代码给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友参考下吧 html post请求之a标签的两种用法 ...

  4. html post举例,html post请求之a标签的两种用法举例

    html post请求之a标签的两种用法举例 1.使用ajax来发起POST请求 HTML代码如下:发起POST请求a> JQuery代码如下:$(".a_post").on ...

  5. java sort 第二个参数_详解java Collections.sort的两种用法

    Collections是一个工具类,sort是其中的静态方法,是用来对List类型进行排序的,它有两种参数形式: public static > void sort(List list) { l ...

  6. c++ operator操作符的两种用法:重载和隐式类型转换,string转其他基本数据类型的简洁实现string_cast...

    C++中的operator主要有两个作用,一是操作符的重载,一是自定义对象类型的隐式转换.对于操作符的重载,许多人都不陌生,但是估计不少人都不太熟悉operator的第二种用法,即自定义对象类型的隐式 ...

  7. include virtual引入html文件,ASP文件引用include file和include virtual两种用法

    在 ASP 编程中,我们经常遇到需要重复使用的模块代码,通常我们将这些模块代码保存为一个单独的文件,需要使用此模块代码时,在程序中通过 #include 指令引用此文件,这样使得工作效率和程序可读性大 ...

  8. python匿名函数Lambda的两种用法

    python匿名函数Lambda的两种用法 第一种方式:作为函数对象单独使用 第二种方式:放在另一函数里使用 一般来说匿名函数Lambda的使用就是为了避免单独def一个函数,而且不用给函数命名,但是 ...

  9. operator的两种用法

    C++ operator两种用法 C++中的operator,有两种用法,一种是operator overloading(操作符重载),一种是operator casting(操作隐式转换).下面分别 ...

最新文章

  1. Android自定义水波纹动画Layout
  2. 买不起手办就用AI渲染一个!用网上随便搜的图就能合成,已有网友开炒游戏NFT...
  3. textisselectable长按再点击_微信朋友圈如何发布长视频?原来打开这个功能就可以,涨知识了...
  4. Spring Boot 内置Tomcat——IntelliJ IDEA中配置模块目录设为文档根目录(DocumentRoot)解决方案
  5. MySql 存储过程实例(附完整注释)
  6. 转:MVC3系列:~Html.BeginForm与Ajax.BeginForm
  7. .net 垃圾回收学习[How To: Use CLR Profiler][翻译学习]【2】
  8. 使用PostgREST的RestAPI操作之安装教程
  9. 是什么决定了创业的成败?
  10. 切片 go 去除第一个_Go语言入门指南,带你轻松学Go
  11. C语言期末考试知识点
  12. Solana代码解析
  13. 法国奢侈品牌VILEBREQUIN限时精品店登陆北京老佛爷百货
  14. 期货客户开户手续费(期货开户最低手续费)
  15. libssl-dev : 依赖: libssl1.0.0 (= 1.0.2g-1ubuntu4.13) 但是 1.0.2n-1ubuntu5.1 正要被安装
  16. Second-Order Cone Programming(SOCP) 二阶锥规划
  17. OpenStack裸金属使用总结
  18. 2021,前端月薪30K已是白菜价?
  19. audioread函数用法(matlab)
  20. 《魔兽争霸3》怎么打兽族内战

热门文章

  1. android 自己定义水平和圆形progressbar 仅仅定义一些style就能够
  2. 读《不要告诉我你懂margin(海玉的博客)》有感
  3. zigbee cc2530地址空间 layout 和flash操作
  4. 推荐几本对创业者很有用的书籍
  5. 注解@PostConstruct与@PreDestroy
  6. 【深入理解JVM】JVM垃圾回收机制
  7. php7连接mongodb,批量添加数据
  8. 云盒子企业网盘入驻阿里云市场,正式向公有云市场发力!
  9. 新鲜出炉的电信诈骗经历
  10. 输出枚举类型的值(seqmentation fault)