大神们是怎么使用ThreadLocal的?

简介: 这篇文章是关于ThreadLocal的第三篇文章。本文将挑选一些主流的Java开源框架,从源码上分析,大神们是如何使用ThreadLocal的,学习他们的设计思想。

这篇文章是关于ThreadLocal的第三篇文章。本文将挑选一些主流的Java开源框架,从源码上分析,大神们是如何使用ThreadLocal的,学习他们的设计思想。

大家可以直接打开github,搜索相应的项目,然后在项目中搜索相关的类,即可看到源代码。


Quartz


Quartz是一个非常知名的开源任务调度系统。

我们要看的源码是Quartz的SimpleSemaphore这个类。它是一个信号量的实现,在生产者-消费者模型里,信号量代表的就是队列里有多少item需要处理。

在信号量的模型里面有一个“等待”操作。当消费者消费完后,会轮询等待。SimpleSemaphore有一个获取锁的方法obtainLock(),我们要看的也是这个方法的内部代码:

92行的while循环就是去进行轮询操作,while里面的locks是一个HashSet,为true代表这个lockName对应的锁正在被别的线程持有,所以当前线程需要等待。

我们看到,在while循环的外层86行,有一个判断,其实是用到了ThreadLocal。

这个外层的判断起什么作用呢?其实是判断当前线程是否已经持有了这个锁。如果持有了,那就直接跳到最后return true了。因为同一个线程,可能有多个程序片段会调用这个获取锁的方法。

可以看到,使用ThreadLocal可以非常高效地判断当前线程的状态,可以快速检测出当前线程是否已经获取了锁,避免了后续锁的检测和争用。


Mybatis


Mybatis不用多说,搞Java的应该都听过或者用过。我们今天要介绍的是它的SqlSessionManager。

Mybatis是一个持久化框架。持久化框架,必然会面临事务的问题。我们的数据库(比如MySQL)可以保证本地事务,但也要求必须在同一个连接才行。

应用程序使用MyBatis,可能会在多个程序片段去访问数据库,做一些增删改查的操作。它们可能需要在同一个事务里面。

举个例子,我们修改完订单状态后,可能还需要修改积分,它们应该在同一个事务里。

Mybatis使用SqlSessionManager保证了我们同一个线程取出来的连接总是同一个。它是如何做到的呢?其实很简单,就是内部使用了一个ThreadLocal。

然后所有的创建连接、取连接都是通过这个ThreadLocal变量的get/set方法进行操作。

private final ThreadLocal<SqlSession> localSqlSession = new ThreadLocal<>();
// 创建连接
public void startManagedSession() {
    this.localSqlSession.set(openSession());
}
// 取连接
@Override
public Connection getConnection() {
    final SqlSession sqlSession = localSqlSession.get();
    if (sqlSession == null) {
        throw new SqlSessionException("Error:  Cannot get connection.  No managed session is started.");
    }
    return sqlSession.getConnection();
}  
复制代码


总结


其实ThreadLocal使用起来是很简单的,这也是ThreadLocal设计的初衷。

使用ThreadLocal,可以保存线程的状态,使得多个程序片段可以很方便地得到当前线程的数据,而不会对其它线程造成影响,也不需要上锁同步。

所以,使用ThreadLocal可以“避免”一些多线程问题,开发安全高效的应用程序。

目录
相关文章
|
7月前
|
存储 Java Spring
ThreadLocal用法
ThreadLocal用法
59 0
|
7月前
|
存储 安全 Java
面试题:用过ThreadLocal吗?ThreadLocal是在哪个包下的?看过ThreadLocal源码吗?讲一下ThreadLocal的get和put是怎么实现的?
字节面试题:用过ThreadLocal吗?ThreadLocal是在哪个包下的?看过ThreadLocal源码吗?讲一下ThreadLocal的get和put是怎么实现的?
86 0
|
5月前
|
存储 算法 Java
ThreadLocal 源码浅析
【7月更文挑战第5天】`ThreadLocal` 是Java中用于创建线程局部变量的工具类,确保每个线程拥有独立的变量副本。源码中,每个`ThreadLocal`实例都有一个唯一的哈希码用于映射到`ThreadLocalMap`,这个内部静态类使用弱引用存储键(`ThreadLocal`实例)以防止内存泄漏。`ThreadLocalMap`使用 Entry 数组,Entry 是一个扩展了 WeakReference 的类,持有线程变量值。`ThreadLocal`的`get()`和`set()`方法通过哈希计算定位并访问或设置线程局部变量。
|
存储 Java
大厂是怎么用ThreadLocal?ThreadLocal核心原理分析
ThreadLocal**是Java中的一个线程本地变量类。它可以让每个线程都有自己独立的变量副本,而不会相互影响。
125 1
|
存储 SpringCloudAlibaba Java
浅析ThreadLocal使用及实现原理
提供了线程局部 (thread-local) 变量。这些变量不同于它们的普通对应物,因为访问某个变量(通过其`get` 或 `set`方法)的每个线程都有自己的局部变量,它独立于变量的初始化副本。`ThreadLocal`实例通常是类中的 private static 字段,它们希望将状态与某一个线程(例如,用户 ID 或事务 ID)相关联 。所以ThreadLocal与线程同步机制不同,线程同步机制是多个线程共享同一个变量,而ThreadLocal是为每一个线程创建一个单独的变量副本,故而每个线程都可以独立地改变自己所拥有的变量副本,而不会影响其他线程所对应的副本。可以这么说Th
116 0
浅析ThreadLocal使用及实现原理
|
存储 Java 数据安全/隐私保护
ThreadLocal的实现原理&源码解析
ThreadLocal是Java中的一个线程封闭机制,它提供了一种线程局部变量的解决方案,可以使每个线程都拥有自己独立的变量副本,互不干扰。
99 0
|
存储 安全 Java
ThreadLocal源码分析
ThreadLocal,即线程局部变量。主要用于线程间数据隔离。这些变量在多线程环境下访问(通过get或set方法访问)时能保证各个线程里的变量相对独立于其他线程内的变量,ThreadLocal实例通常来说都是private static类型。ThreadLocal不是为了解决多线程访问共享变量,而是为每个线程创建一个单独的变量副本,提供了保持对象的方法和避免参数传递的复杂性。
|
存储 安全 Java
|
安全 Java
ThreadLocal相关知识点
ThreadLocal相关知识点
112 0
ThreadLocal相关知识点
下一篇
DataWorks