java 独立存储线程变量技术——ThreadLocal

来源:互联网 发布:微信数据怎么放到sd卡 编辑:程序博客网 时间:2024/05/21 18:23

在多线程编程中,我们使用(synchronized,ReentrantLock等)来确保多个线程共享的变量能被安全的访问。但是还有一些变量,我们希望每一个线程都能保存一份独立的值而不受其他线程的影响。这个时候我们就需要用到ThreadLocal这个类来完成相关操作。

ThreadLocal的作用


现有两个线程A和B,它们都能访问到一个变量str_c。在不经过任何处理时,str_c的值可以被A和B两个线程访问和修改。使用了ThreadLocal后将str_c作为一个线程的局部变量,对于每一个线程,通过ThreadLocal方法得到的str_c的值是该线程的str_c的值,这个值不会被其他线程修改,其他线程只能修改他们自己的str_c的值。在并发的代码中的任何一点我们都能访问ThreadLocal而获取str_c的值,但是获取的值是该线程的值,其他线程的str_c在这个时候被“屏蔽”了,一般情况下我们看不见且访问不到。

在工作项目中举例。在Java ee的springMVC框架中,我们在封装Controller时习惯于将request、response两个对象通过ThreadLocal封装,因为这两个对象在每个线程中的内容肯定不同,通过这种技术,可以确保在高并发情况下的安全性。

ThreadLocal与Synchronized比较


网上的部分博客对ThreadLocal与Synchronized的概念混淆不清。ThreadLocal的作用并不是取代Synchronized,这两种方法从初衷上就完全不同。不仅仅是初衷,这两种技术的实现方法也不同,不存在可比性。

ThreadLocal: 将每个线程持有的变量安全的存放起来,不被其他线程访问。
synchronized: 让多个线程并发访问的变量能够安全的被访问和操作。

ThreadLocal使用方法


ThreadLocal类本身并不是线程,这个类是用来创建并存放线程局部变量的。

方法 含义 initialValue 返回此线程局部变量的当前线程的“初始值”。线程第一次调用get方法前会调用此方法。 get 返回此线程局部变量的当前线程副本中的值。 set 将此线程局部变量的当前线程副本中的值设置为指定值。 remove 移除此线程局部变量当前线程的值。

ThreadLocal 提供了线程局部变量并且通常是类中的 private static 字段,它们希望将状态与某一个线程(例如,用户 ID 或事务 ID)相关联。 例如,以下类通过重写initialValue方法生成对每个线程唯一的局部标识符。线程 ID 是在第一次调用 UniqueThreadIdGenerator.getCurrentThreadId() 时分配的,在后续调用中不会更改。

import java.util.concurrent.atomic.AtomicInteger; public class UniqueThreadIdGenerator {     private static final AtomicInteger uniqueId = new AtomicInteger(0);     private static final ThreadLocal < Integer > uniqueNum =          new ThreadLocal < Integer > () {             @Override protected Integer initialValue() {                 return uniqueId.getAndIncrement();         }     };     public static int getCurrentThreadId() {         return uniqueNum.get();     } } 

ThreadLocal实现原理


ThreadLocal的实现方法有些复杂,愚以为这个技术可以不采用Map的方式来存放,其他的键值对存放方式也未尝不可,但是jdk采用的方法肯定有他正确的道理。ThreadLocal存放局部变量的底层实现主要涉及到三个类:ThreadLocal、ThreadLocalMap、Thread

ThreadLocal:
在这个类中,每当调用set方法传入值时先获得当前线程Thread对象,在Thread对象的私有变量中查看ThreadLocal.ThreadLocalMap类对象是否为空,如果不为空,将值和threadLocal的this对象传入ThreadLocalMap类中。

ThreadLocalMap:
ThreadLocalMap是TheadLocal的静态内部类,这也能够解释为什么在Thread类中ThreadLocalMap可以通过ThreadLocal.ThreadLocalMap(外部类.内部类)的方式声明。此类是一个简单实现的Map映射表和java集合框架中的Map类无关系。当有值传入时将线程对象和值以键值对的形式存放。

Thread:
这个类是当前线程类,其中包含ThreadLocal.ThreadLocalMap类型的私有变量,用该变量来存放本线程的局部变量,从而达到其他线程不能访问的效果。

阅读全文
1 0
原创粉丝点击