文章目录

  • 在Map中存储用户数据
  • 在ThreadLocal中存储用户数据

java中ThreadLocal的使用

ThreadLocal主要用来为当前线程存储数据,这个数据只有当前线程可以访问。

在定义ThreadLocal的时候,我们可以同时定义存储在ThreadLocal中的特定类型的对象。

ThreadLocal<Integer> threadLocalValue = new ThreadLocal<>();

上面我们定义了一个存储Integer的ThreadLocal对象。

要存储和获取ThreadLocal中的对象也非常简单,使用get()和set()即可:

threadLocalValue.set(1);
Integer result = threadLocalValue.get();

我可以将ThreadLocal看成是一个map,而当前的线程就是map中的key。

除了new一个ThreadLocal对象,我们还可以通过:

    public static <S> ThreadLocal<S> withInitial(Supplier<? extends S> supplier) {return new SuppliedThreadLocal<>(supplier);}

ThreadLocal提供的静态方法withInitial来初始化一个ThreadLocal。

ThreadLocal<Integer> threadLocal = ThreadLocal.withInitial(() -> 1);

withInitial需要一个Supplier对象,通过调用Supplier的get()方法获取到初始值。

要想删除ThreadLocal中的存储数据,可以调用:

threadLocal.remove();

下面我通过两个例子的对比,来看一下使用ThreadLocal的好处。

在实际的应用中,我们通常会需要为不同的用户请求存储不同的用户信息,一般来说我们需要构建一个全局的Map,来根据不同的用户ID,来存储不同的用户信息,方便在后面获取。

在Map中存储用户数据

我们先看下如果使用全局的Map该怎么用:

public class SharedMapWithUserContext implements Runnable {public static Map<Integer, Context> userContextPerUserId= new ConcurrentHashMap<>();private Integer userId;private UserRepository userRepository = new UserRepository();public SharedMapWithUserContext(int i) {this.userId=i;}@Overridepublic void run() {String userName = userRepository.getUserNameForUserId(userId);userContextPerUserId.put(userId, new Context(userName));}
}

这里我们定义了一个static的Map来存取用户信息。

再看一下怎么使用:

    @Testpublic void testWithMap(){SharedMapWithUserContext firstUser = new SharedMapWithUserContext(1);SharedMapWithUserContext secondUser = new SharedMapWithUserContext(2);new Thread(firstUser).start();new Thread(secondUser).start();assertEquals(SharedMapWithUserContext.userContextPerUserId.size(), 2);}

在ThreadLocal中存储用户数据

如果我们要在ThreadLocal中使用可以这样:

public class ThreadLocalWithUserContext implements Runnable {private static ThreadLocal<Context> userContext= new ThreadLocal<>();private Integer userId;private UserRepository userRepository = new UserRepository();public ThreadLocalWithUserContext(int i) {this.userId=i;}@Overridepublic void run() {String userName = userRepository.getUserNameForUserId(userId);userContext.set(new Context(userName));System.out.println("thread context for given userId: "+ userId + " is: " + userContext.get());}}

测试代码如下:

public class ThreadLocalWithUserContextTest {@Testpublic void testWithThreadLocal(){ThreadLocalWithUserContext firstUser= new ThreadLocalWithUserContext(1);ThreadLocalWithUserContext secondUser= new ThreadLocalWithUserContext(2);new Thread(firstUser).start();new Thread(secondUser).start();}
}

运行之后,我们可以得到下面的结果:

thread context for given userId: 1 is: com.flydean.Context@411734d4
thread context for given userId: 2 is: com.flydean.Context@1e9b6cc

不同的用户信息被存储在不同的线程环境中。

注意,我们使用ThreadLocal的时候,一定是我们可以自由的控制所创建的线程。如果在ExecutorService环境下,就最好不要使用ThreadLocal,因为在ExecutorService中,线程是不可控的。

本文的例子可以参考https://github.com/ddean2009/learn-java-concurrency/tree/master/ThreadLocal

更多精彩内容且看:

  • 区块链从入门到放弃系列教程-涵盖密码学,超级账本,以太坊,Libra,比特币等持续更新
  • Spring Boot 2.X系列教程:七天从无到有掌握Spring Boot-持续更新
  • Spring 5.X系列教程:满足你对Spring5的一切想象-持续更新
  • java程序员从小工到专家成神之路(2020版)-持续更新中,附详细文章教程

更多教程请参考 flydean的博客

java中ThreadLocal的使用相关推荐

  1. Java中ThreadLocal的深入理解

    官方对ThreadLocal的描述: "该类提供了线程局部(thread-local)变量.这些变量不同于它们的普通对应物,因为访问某个变量(通过其get或set方法)的每个线程都有自己的局 ...

  2. 帮助理解Java中ThreadLocal的一篇文章

    原文地址:http://www.ahlinux.com/java/20332.html 并发编程中,一个重要的内容是数据共享.当你创建了实现Runnable接口的线程,然后开启使用相同Runnable ...

  3. 【Java】Java中ThreadLocal简介以及源码

    文章目录 1.概述 1.1 什么是ThreadLocal变量 2.API 方法 4.3 ThreadLocalMap 4.1 ThreadLocal 4.1.1 set 4.1.2 get 4.1.2 ...

  4. 【java】ThreadLocal 内存泄漏 代码演示 实例演示

    1.概述 转载:ThreadLocal 内存泄漏 代码演示 实例演示 首先看文章:ThreadLocal内存泄露原因分析 相关文章: [高并发]ThreadLocal.InheritableThrea ...

  5. Java中的ThreadLocal详解

    一.ThreadLocal简介 多线程访问同一个共享变量的时候容易出现并发问题,特别是多个线程对一个变量进行写入的时候,为了保证线程安全,一般使用者在访问共享变量的时候需要进行额外的同步措施才能保证线 ...

  6. Java中的ThreadLocal的使用--学习笔记

    ThreadLocal直译为"线程本地"或"本地线程",如果你真的这么认为,那就错了!其实它就是一个容器,用于存放线程的局部变量,我认为应该叫做ThreadLo ...

  7. 4问教你搞定java中的ThreadLocal

    摘要:ThreadLocal是除了加锁同步方式之外的一种保证规避多线程访问出现线程不安全的方法. 本文分享自华为云社区<4问搞定java中的ThreadLocal>,作者:breakDra ...

  8. java产生死锁的主要原因_详解java中产生死锁的原因及如何避免

    1. Java中导致死锁的原因 Java中死锁最简单的情况是,一个线程T1持有锁L1并且申请获得锁L2,而另一个线程T2持有锁L2并且申请获得锁L1,因为默认的锁申请操作都是阻塞的,所以线程T1和T2 ...

  9. (转)Spring中ThreadLocal的认识

    我们知道Spring通过各种DAO模板类降低了开发者使用各种数据持久技术的难度.这些模板类都是线程安全的,也就是说,多个DAO可以复用同一个模板实例而不会发生冲突.我们使用模板类访问底层数据,根据持久 ...

最新文章

  1. 斗地主发牌编程PHP,JAVA代码之斗地主发牌详解
  2. UVA1584 ​​​​​​​Circular Sequence【字符串】
  3. TensorFlow4-常量和变量及TensorBoard使用
  4. HDU4907小技巧
  5. 2021年内衣品牌营销传播方案-婧麒+美柚.pdf(附下载链接)
  6. arp协议的主要功能是_计算机网络之ARP协议
  7. [SSH] 为 GitLab 帐号添加 SSH keys
  8. 糖原代谢疾病行业调研报告 - 市场现状分析与发展前景预测
  9. Ubuntu免密码输入关机脚本
  10. 微信公众号服务号申请注册教程
  11. 利用LSTM自动生成中文文本
  12. “醉牛前端”重新起航!
  13. 非科班学弟如何转行斩获 ATM 大厂的 Offer ?
  14. python定向爬取淘宝中商品的名称和价格
  15. 戒指在不同手指的意义
  16. c语言程序设计青岛职业技术学院,2020年知道C语言程序设计(青岛职业技术学院)答案公众号...
  17. 三菱FX3U与台达VFD M变频器通讯教程
  18. 关于自己使用Docker安装托管OpenStreetMap(OSM)贴片踩过的几个问题及解决
  19. Pytorch 基于NiN的服饰识别(使用Fashion-MNIST数据集)
  20. DAMA-第三章(数据治理)

热门文章

  1. Socket重叠IO
  2. 1.5 MFC封装思想
  3. cocos2d-x初探学习笔记(16)--LayerColor
  4. 深度探索I/O完成端口
  5. Scrapy中的get_project_settings 读取设置文件
  6. selenium的使用教程2
  7. ​Golang 并发编程指南
  8. 使用VMware VSphere WebService SDK进行开发 (一)——基本信息阐述
  9. 内联函数和编译器对Go代码的优化
  10. Mozilla发布最大公共语音数据集Common Voice