threadlocal原理及常用应用场景2
来源:互联网 发布:化工公司工艺软件 编辑:程序博客网 时间:2024/06/06 03:37
最近项目中遇到如下的场景:在执行数据迁移时,需要按照用户粒度加锁,因此考虑使用排他锁,迁移工具和业务服务属于两个服务,因此需要使用分布式锁。
我们使用缓存(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);
- }
- }
- 作者:杜琪
- 链接:http://www.jianshu.com/p/cadd53f063b9
因为每个线程可能携带不同的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变量,则该变量的副本会提交给垃圾回收器。
- /**
- * {@link ThreadLocal} subclass that exposes a specified name
- * as {@link #toString()} result (allowing for introspection).
- *
- * @author Juergen Hoeller
- * @since 2.5.2
- * @see NamedInheritableThreadLocal
- */
- public class NamedThreadLocal<T> extends ThreadLocal<T> {
- private final String name;
- /**
- * Create a new NamedThreadLocal with the given name.
- * @param name a descriptive name for this ThreadLocal
- */
- public NamedThreadLocal(String name) {
- Assert.hasText(name, "Name must not be empty");
- this.name = name;
- }
- @Override
- public String toString() {
- return this.name;
- }
- }
- XmlBeanDefinitionReader.java
- private final ThreadLocal<Set<EncodedResource>> resourcesCurrentlyBeingLoaded =
- new NamedThreadLocal<Set<EncodedResource>>("XML bean definition resources currently being loaded");
- /**
- * Load bean definitions from the specified XML file.
- * @param encodedResource the resource descriptor for the XML file,
- * allowing to specify an encoding to use for parsing the file
- * @return the number of bean definitions found
- * @throws BeanDefinitionStoreException in case of loading or parsing errors
- */
- public int loadBeanDefinitions(EncodedResource encodedResource) throws BeanDefinitionStoreException {
- Assert.notNull(encodedResource, "EncodedResource must not be null");
- if (logger.isInfoEnabled()) {
- logger.info("Loading XML bean definitions from " + encodedResource.getResource());
- }
- Set<EncodedResource> currentResources = this.resourcesCurrentlyBeingLoaded.get();
- if (currentResources == null) {
- currentResources = new HashSet<EncodedResource>(4);
- this.resourcesCurrentlyBeingLoaded.set(currentResources);
- }
- if (!currentResources.add(encodedResource)) {
- throw new BeanDefinitionStoreException(
- "Detected cyclic loading of " + encodedResource + " - check your import definitions!");
- }
- try {
- InputStream inputStream = encodedResource.getResource().getInputStream();
- try {
- InputSource inputSource = new InputSource(inputStream);
- if (encodedResource.getEncoding() != null) {
- inputSource.setEncoding(encodedResource.getEncoding());
- }
- return doLoadBeanDefinitions(inputSource, encodedResource.getResource());
- }
- finally {
- inputStream.close();
- }
- }
- catch (IOException ex) {
- throw new BeanDefinitionStoreException(
- "IOException parsing XML document from " + encodedResource.getResource(), ex);
- }
- finally {
- currentResources.remove(encodedResource);
- if (currentResources.isEmpty()) {
- this.resourcesCurrentlyBeingLoaded.remove();
- }
- }
- }
阅读全文
0 0
- threadlocal原理及常用应用场景2
- threadlocal原理及常用应用场景
- threadlocal原理及常用应用场景1
- threadlocal原理及常用应用场景
- java ThreadLocal(应用场景及使用方式及原理)
- java ThreadLocal(应用场景及使用方式及原理)
- ThreadLocal(应用场景及使用方式及原理)
- java ThreadLocal(应用场景及使用方式及原理)
- ThreadLocal原理及应用
- ThreadLocal内部实现及应用场景
- ThreadLocal 的应用及原理
- 【ZooKeeper 2】ZooKeeper原理及应用场景
- ThreadLocal使用、场景、原理
- zookeeper原理及应用场景
- Zookeeper原理及应用场景
- 马尔科夫原理及应用场景
- ThreadLocal的底层实现原理与应用场景
- Android线程管理之ThreadLocal理解及应用场景
- 12月6日 数据结构 周三
- jQuery AJAX
- Python学习笔记----装饰器
- Java中的正则表达式
- Java服务端推送和web端推送——GoEasy免费推送服务
- threadlocal原理及常用应用场景2
- LOJ6002 「网络流 24 题
- react踩坑不完全指北(1)
- Python,列表
- 递归再理解
- sublime text3安装以及插件配置教程
- Java设计模式透析之 —— 模板方法(Template Method)
- layout_below与layout_alignBottom的区别
- poi工具类