ThreadLocal的使用场景

最近项目中遇到如下的场景:在执行数据迁移时,需要按照用户粒度加锁,因此考虑使用排他锁,迁移工具和业务服务属于两个服务,因此需要使用分布式锁。

我们使用缓存(Tair或者Redis)实现分布式锁,具体代码如下:

@Service
public class Locker {
    @Resource(name = "tairClientUtil")
    private TairClientUtil tairClientUtil;

    private ThreadLocal<Long> lockerBeanThreadLocal = new ThreadLocal<>();

    public void init(long userid) {
        lockerBeanThreadLocal.remove();
        lockerBeanThreadLocal.set(userid);
    }

    public void updateLock() {
        String lockKey = Constants.MIGRATION_PREFIX + lockerBeanThreadLocal.get();
        tairClientUtil.incr(lockKey, Constants.COUNT_EXPIRE);
    }

    public void invalidLock() {
        String lockKey = Constants.MIGRATION_PREFIX + lockerBeanThreadLocal.get();
        tairClientUtil.invalid(lockKey);
    }
}

因为每个线程可能携带不同的userid发起请求,因此在这里使用ThreadLocal变量存放userid,使得每个线程都有一份自己的副本。

参考官方文档:ThreadLocal的用法,这个类提供“thread-local”变量,这些变量与线程的局部变量不同,每个线程都保存一份改变量的副本,可以通过get或者set方法访问。如果开发者希望将类的某个静态变量(user ID或者transaction ID)与线程状态关联,则可以考虑使用ThreadLocal。

举个例子,下面的类为每个线程生成不同的ID,当某个线程第一次调用Thread.get()时,会为该线程赋予一个ID,并且在后续的调用中不再改变。

 import java.util.concurrent.atomic.AtomicInteger;

 public class ThreadId {
     // Atomic integer containing the next thread ID to be assigned
     private static final AtomicInteger nextId = new AtomicInteger(0);

     // Thread local variable containing each thread's ID
     private static final ThreadLocal<Integer> threadId =
         new ThreadLocal<Integer>() {
             @Override protected Integer initialValue() {
                 return nextId.getAndIncrement();
         }
     };

     // Returns the current thread's unique ID, assigning it if necessary
     public static int get() {
         return threadId.get();
     }
 }

每个线程会“隐式”包含一份thread-local变量的副本,只要线程还处于活跃状态,就可以访问该变量;当线程停止后,如果没有其他线程持有该thread-local变量,则该变量的副本会提交给垃圾回收器。

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏Java3y

Spring入门这一篇就够了

前言 前面已经学习了Struts2和Hibernate框架了。接下来学习的是Spring框架…本博文主要是引入Spring框架… Spring介绍 Spring...

2.7K60
来自专栏张泽旭的专栏

基于spring boot ftp文件上传

对ftp文件上传将行封装,实现连接的单例模式,完成线程安全的改进,ftp文件上传下载失败的重试。

75410
来自专栏崔庆才的专栏

Scrapy框架的使用之Item Pipeline的用法

2K40
来自专栏Spring相关

oauth2.0实现sso单点登录的方式和相关代码

百科:SSO英文全称Single Sign On,单点登录。SSO是在多个应用系统中,用户只需要登录一次就可以访问所有相互信任的应用系统。它包括可以将这次主要的...

67020
来自专栏张泽旭的专栏

基于spring boot sftp文件上传

对sftp文件上传将行封装,实现连接的单例模式,完成线程安全的改进,sftp文件上传下载失败的重试。

44110
来自专栏有趣的django

Django rest framework(5)----解析器

解析器  (1)api/urls.py # api/urls.py from django.urls import path,re_path from .v...

48350
来自专栏行者常至

mysql mybatis 批量更新

版权声明:本文为博主原创文章,允许转载,请标明出处。 https://blog.csdn.net/qwdafedv/article/deta...

49610
来自专栏扎心了老铁

一个scrapy框架的爬虫(爬取京东图书)

我们的这个爬虫设计来爬取京东图书(jd.com)。 scrapy框架相信大家比较了解了。里面有很多复杂的机制,超出本文的范围。 1、爬虫spider tips:...

46560
来自专栏A周立SpringCloud

Spring Boot、Dubbo项目Mock测试踩坑与总结

本文是对Spring Boot、Dubbo项目进行Mock测试的总结与踩坑实录。 搜索了一圈,居然没发现类似的文章,莫非用Dubbo的朋友们都不Mock测试,或...

78480
来自专栏机器学习从入门到成神

PyCharm下进行Scrapy项目的调试

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/sinat_35512245/articl...

46420

扫码关注云+社区

领取腾讯云代金券