要了解ThreadLocal,首先搞清楚ThreadLocal 是什么?是用来解决什么问题的?

ThreadLocal 是线程的局部变量, 是每一个线程所单独持有的,其他线程不能对其进行访问, 通常是类中的 private static 字段,是对该字段初始值的一个拷贝,它们希望将状态与某一个线程(例如,用户 ID 或事务 ID)相关联

我们知道有时候一个对象的变量会被多个线程所访问,这时就会有线程安全问题,当然我们可以使用synchorinized 关键字来为此变量加锁,进行同步处理,从而限制只能有一个线程来使用此变量,但是加锁会大大影响程序执行效率,此外我们还可以使用ThreadLocal来解决对某一个变量的访问冲突问题。

当使用ThreadLocal维护变量的时候 为每一个使用该变量的线程提供一个独立的变量副本,即每个线程内部都会有一个该变量,这样同时多个线程访问该变量并不会彼此相互影响,因此他们使用的都是自己从内存中拷贝过来的变量的副本, 这样就不存在线程安全问题,也不会影响程序的执行性能。

但是要注意,虽然ThreadLocal能够解决上面说的问题,但是由于在每个线程中都创建了副本,所以要考虑它对资源的消耗,比如内存的占用会比不使用ThreadLocal要大。

ThreadLocal 方法使用详解

ThreadLocal 的几个方法: ThreadLocal 可以存储任何类型的变量对象, get返回的是一个Object对象,但是我们可以通过泛型来制定存储对象的类型。

  1. public T get() { } // 用来获取ThreadLocal在当前线程中保存的变量副本
  2. public void set(T value) { } //set()用来设置当前线程中变量的副本
  3. public void remove() { } //remove()用来移除当前线程中变量的副本
  4. protected T initialValue() { } //initialValue()是一个protected方法,一般是用来在使用时进行重写的

Thread 在内部是通过ThreadLocalMap来维护ThreadLocal变量表, 在Thread类中有一个threadLocals 变量,是ThreadLocalMap类型的,它就是为每一个线程来存储自身的ThreadLocal变量的, ThreadLocalMap是ThreadLocal类的一个内部类,这个Map里面的最小的存储单位是一个Entry, 它使用ThreadLocal作为key, 变量作为 value,这是因为在每一个线程里面,可能存在着多个ThreadLocal变量

初始时,在Thread里面,threadLocals为空,当通过ThreadLocal变量调用get()方法或者set()方法,就会对Thread类中的threadLocals进行初始化,并且以当前ThreadLocal变量为键值,以ThreadLocal要保存的副本变量为value,存到threadLocals。 
然后在当前线程里面,如果要使用副本变量,就可以通过get方法在threadLocals里面查找

ThreadLocal是如何为每一个线程创建一个变量副本的,下面举一个例子来看一看。例子来源于 博客http://www.cnblogs.com/dolphin0520/p/3920407.html

  1. public class ThreadLocalTest {
  2. public static void main(String[] args) throws InterruptedException {
  3. final ThreadLocalTest test = new ThreadLocalTest();
  4. test.set();
  5. System.out.println(test.getLong());
  6. System.out.println(test.getString());
  7. // 在这里新建了一个线程
  8. Thread thread1 = new Thread() {
  9. public void run() {
  10. test.set(); // 当这里调用了set方法,进一步调用了ThreadLocal的set方法是,会将ThreadLocal变量存储到该线程的ThreadLocalMap类型的成员变量threadLocals中,注意的是这个threadLocals变量是Thread线程的一个变量,而不是ThreadLocal类的变量。
  11. System.out.println(test.getLong());
  12. System.out.println(test.getString());
  13. };
  14. };
  15. thread1.start();
  16. thread1.join();
  17. System.out.println(test.getLong());
  18. System.out.println(test.getString());
  19. }
  20. ThreadLocal<Long> longLocal = new ThreadLocal<Long>();
  21. ThreadLocal<String> stringLocal = new ThreadLocal<String>();
  22. public void set() {
  23. longLocal.set(Thread.currentThread().getId());
  24. stringLocal.set(Thread.currentThread().getName());
  25. }
  26. public long getLong() {
  27. return longLocal.get();
  28. }
  29. public String getString() {
  30. return stringLocal.get();
  31. }
  32. }

代码的输出结果: 

main 

Thread-0 

main

ThreadLocal 的应用场景

最常见的ThreadLocal使用场景为 
用来解决 数据库连接、Session管理等。

数据库连接:

  1. Class A implements Runnable{
  2. private static ThreadLocal<Connection> connectionHolder = new ThreadLocal<Connection>() {
  3. public Connection initialValue() {
  4. return DriverManager.getConnection(DB_URL);
  5. }
  6. };
  7. public static Connection getConnection() {
  8. return connectionHolder.get();
  9. }
  10. }

Session管理

  1. private static final ThreadLocal threadSession = new ThreadLocal();
  2. public static Session getSession() throws InfrastructureException {
  3. Session s = (Session) threadSession.get();
  4. try {
  5. if (s == null) {
  6. s = getSessionFactory().openSession();
  7. threadSession.set(s);
  8. }
  9. } catch (HibernateException ex) {
  10. throw new InfrastructureException(ex);
  11. }
  12. return s;
  13. }

多线程 ThreadLocal的更多相关文章

  1. Java多线程——ThreadLocal类的原理和使用

    Java多线程——ThreadLocal类的原理和使用 摘要:本文主要学习了ThreadLocal类的原理和使用. 概述 是什么 ThreadLocal可以用来维护一个变量,提供了一个ThreadLo ...

  2. 多线程--ThreadLocal类

    一.ThreadLocal类简介--此类是在整个开发过程中至关重要的类,他主要是在开发过程中解决了核心资源和多线程并发访问的处理情况--在真正去了解ThreadLocal类作用的时候,我们可以先编写一 ...

  3. Java多线程——ThreadLocal类

    一.概述   ThreadLocal是什么呢?其实ThreadLocal并非是一个线程的本地实现版本,它并不是一个Thread,而是threadlocalvariable(线程局部变量).也许把它命名 ...

  4. [Java多线程]-ThreadLocal源码及原理的深入分析

    ThreadLocal<T>类:以空间换时间提供一种多线程更快捷访问变量的方式.这种方式不存在竞争,所以也不存在并发的安全性问题. //-------------------------- ...

  5. Java多线程ThreadLocal介绍

    在Java多线程环境下ThreadLocal就像一家银行,每个线程就是银行里面的一个客户,每个客户独有一个保险箱来存放金钱,客户之间的金钱不影响. private static ThreadLocal ...

  6. 深入理解Java多线程——ThreadLocal

    目录 定义 API 场景分析 场景实验,观察Spring框架在多线程场景的执行情况 10000此请求,单线程 10000次请求,线程数加到100 对c的访问加锁 把c设为ThreadLocal 收集多 ...

  7. 一步一步学多线程-ThreadLocal源码解析

    上网查看了很多篇ThreadLocal的原理的博客,上来都是文字一大堆,费劲看了半天,大脑中也没有一个模型,想着要是能够有一张图明确表示出来ThreadLocal的设计该多好,所以就自己看了源码,画了 ...

  8. JAVA多线程---ThreadLocal<E>

    p.p1 { margin: 0.0px 0.0px 0.0px 0.0px; font: 13.0px ".SF NS Text" } tips: 1 当前ThreadLocal ...

  9. java多线程-ThreadLocal

    大纲: 用法 源码 一.用法 ThreadLocal是一个容器,顾名思义就是把一个变量存到线程本地. class Test { public static void main(String[] arg ...

随机推荐

  1. 【Jmeter自学】Linux环境下Jmeter运行

    ==================================================================================================== ...

  2. [UGUI]图文混排(七):动态表情

    帧动画脚本: http://www.cnblogs.com/lyh916/p/9194823.html 这里的动态表情,我使用的是固定间隔去刷新Image上的Sprite来实现的,即帧动画.这里可以将 ...

  3. EXCEL workbook.saveas 函数详解

    本问所有资料来自于 Excel2003 VBA帮助文件,张荣整理,适用于DELPHI,VB的高级语言操作Excel用 ExcelApplication.WorkBook.SaveAs(filename ...

  4. [Android] SeekBar---可拖动进度条

    SeekBar---可拖动进度条 ()setMax //设置SeekBar最大数值 ()setProgress //设置SeekBar当前数值 ()setSecondaryProgress//设置Se ...

  5. uva-10714-贪心

    题意:有一条杆,长度为L,上面很几只蚂蚁,蚂蚁的朝向未知,爬速1cm/s,在爬行过程中,蚂蚁相撞了就往反方向爬,问,杆上没有蚂蚁至少要多久,至多要多久 解题思路: 蚂蚁1和蚂蚁2相撞,我们只要交换一下 ...

  6. 【转】AD常用端口

    通常在域环境中我们有部分设备在DMZ区时,就需要知道AD的相关端口.在此提供给各位: 用户登录与验证身份时会用到的连接端口用户登录时会用到以下的服务,因此如果用户的计算机与域控制器之间被防火墙隔开,就 ...

  7. spark基础知识介绍2

    dataframe以RDD为基础的分布式数据集,与RDD的区别是,带有Schema元数据,即DF所表示的二维表数据集的每一列带有名称和类型,好处:精简代码:提升执行效率:减少数据读取; 如果不配置sp ...

  8. leetcode1016

    class Solution(object): def queryString(self, S: str, N: int) -> bool: return all(S.find(bin(i)[2 ...

  9. leetcode329

    public class Solution { bool[,] tags;//用于标记是否已经访问过,false未访问,true已访问 int[,] records;//用于标记以当前为起点的最长升序 ...

  10. eclipse中无法新建Android工程 出现问题:Plug-in org.eclipse.ajdt.ui was unable to load

    转自:http://www.bubuko.com/infodetail-757338.html eclipse中打开后新建Android项目区仍无法创建,出现下列提示对话框: Plug-in org. ...