Java中ThreadLocal的深入理解
官方对ThreadLocal的描述:
"该类提供了线程局部(thread-local)变量。这些变量不同于它们的普通对应物,因为访问某个变量(通过其get或set方法)的每个线程都有自己的局部变量,它独立于变量的初始化副本。ThreadLocal实例通常是类中的private static字段,它们希望将状态与某一个线程(例如,用户ID或事物ID)相关联。"
《Thinking in Java》中的描述:
防止任务在共享资源上产生冲突的第二种方式是根除对变量的共享。线程本地存储是一种自动化机制,可以为使用变量的每个不同的线程都创建不同的存储。因此,如果你有5个线程都要使用变量x所表示的对象,那线程本地存储就会生成5个用于x的不同的存储块。主要是,它们使得你可以将状态与线程关联起来。
三个要点:
1.每个线程都有自己的局部变量
每个线程都有一个独立于其它线程的上下文来保存这个变量,一个线程的本地变量对其它线程是不可见的。
2.独立于变量的初始化副本
ThreadLocal可以给一个初始值,而每个线程都会获得这个初始化值的一个副本,这样才能保证不同的线程都有一份拷贝。
3.状态与某一个线程相关联
ThreadLocal不是用于解决共享变量的问题的,不是为了协调线程同步而存在,而是为了方便每个线程处理自己的状态而引入的一个机制,就像《Thinking in Java》中描述的那样:”它们使得你可以将状态与线程关联起来。“理解这点对正确使用ThreadLocal至关重要。
源码举例:

从输出的结果可以看出,五个线程处理自己的本地变量值。

而这个测试的结果,并没有相同。这是因为实例为对象,所以初始值为一个对象的引用,那么五个线程的副本就是这个对象的引用的副本,也就是说这些引用还是指向同一个对象,所以就出现了这种情况。
ThreadLocal的接口方法:
- void set(T value):设置当前线程的线程局部变量的值;
public void set(T value) {
Thread t = Thread.currentThread();
ThreadLocalMap map = getMap(t);
if (map != null)
map.set(this, value);
//说明线程第一次使用线程本地变量(注意这里的第一次含义)
else
createMap(t, value);
}
- public T get():该方法返回当前线程所对应的线程局部变量;
public T get() {
//获取当前执行线程
Thread t = Thread.currentThread();
//取得当前线程的ThreadLocalMap实例
ThreadLocalMap map = getMap(t);
//如果map不为空,说明该线程已经有了一个ThreadLocalMap实例
if (map != null) {
//map中保存线程的所有的线程本地变量,我们要去查找当前线程本地变量
ThreadLocalMap.Entry e = map.getEntry(this);
//如果当前线程本地变量存在这个map中,则返回其对应的值
11 if (e != null)
return (T)e.value;
13 }
//如果map不存在或者map中不存在当前线程本地变量,返回初始值
return setInitialValue();
}
- public void remove():将当前线程局部变量的值删除,目的是为了减少内存的占用,该方法是JDK 5.0新增的方法。当线程结束后,对应该线程的局部变量将被自动垃圾回收,所以显示调用该方法清除线程的局部变量并不是必须的操作,但它可以加快内存回收的速度;
- protected T initialValue():返回该线程局部变量的初始值,该方法是一个protected的方法,显然是为了让子类覆盖而设计的,这个方法是一个延迟调用方法,在线程第1次调用get()或set(T)时才执行,并且仅执行1次。ThreadLocal中的默认实现直接返回一个null。
这里注意,ThreadLocal中是有一个Map,但这个Map不是我们平时使用的Map,而是ThreadLocalMap,ThreadLocalMap是ThreadLocal的一个内部类,不对外使用的。当使用ThreadLocal存值时,首先是获取到当前线程对象,然后获取到当前线程本地变量Map,最后将当前使用的ThreadLocal和传入的值放到Map中,也就是说ThreadLocalMap中存的值是[ThreadLocal对象, 存放的值],这样做的好处是,每个线程都对应一个本地变量的Map,所以一个线程可以存在多个线程本地变量。下面提供一个简单的实现版本:

Java中ThreadLocal的深入理解的更多相关文章
- java中threadlocal的理解
[TOC] #java中threadlocal的理解##一.threadlocal的生命周期和ThreadLocalMap的生命周期可以吧TreadLocal看做是一个map来使用,只不过这个map是 ...
- Java中线程同步的理解 - 其实应该叫做Java线程排队
Java中线程同步的理解 我们可以在计算机上运行各种计算机软件程序.每一个运行的程序可能包括多个独立运行的线程(Thread). 线程(Thread)是一份独立运行的程序,有自己专用的运行栈.线程有可 ...
- java中线程同步的理解(非常通俗易懂)
转载至:https://blog.csdn.net/u012179540/article/details/40685207 Java中线程同步的理解 我们可以在计算机上运行各种计算机软件程序.每一个运 ...
- java中ThreadLocal的使用
文章目录 在Map中存储用户数据 在ThreadLocal中存储用户数据 java中ThreadLocal的使用 ThreadLocal主要用来为当前线程存储数据,这个数据只有当前线程可以访问. 在定 ...
- java中ThreadLocal类的使用
ThreadLocal是解决线程安全问题一个很好的思路,ThreadLocal类中有一个Map,用于存储每一个线程的变量副本,Map中元素的键为线程对象,而值对应线程的变量副本,由于Key值不可重复, ...
- 微冷的雨之Java中的多线程初理解(一)
在讲解多线程前,我们必须理解什么是多线程?而且很多人都会将进程和线程做对比. 进程和线程 进程:进程是操作系统结构的基础,是一次程序的执行,是一个程序及其数据在处理机上顺序执行时所发生的活动,是程序在 ...
- 对Java中字符串的进一步理解
字符串在程序开发中无处不在,也是用户交互所涉及到最频繁的数据类型,那么字符串不仅仅就是我们简单的理解的String str = "abc";一起来更加深入的看一下 在Java中,字 ...
- Java中ThreadLocal的设计与使用
早在Java 1.2推出之时,Java平台中就引入了一个新的支持:java.lang.ThreadLocal,给我们在编写多线程程序时提供了一种新的选择.使用这个工具类可以很简洁地编写出优美的多线程程 ...
- Java学习疑惑(8)----可视化编程, 对Java中事件驱动模型的理解
我们编写程序就是为了方便用户使用, 我觉得UI设计的核心就是简洁, 操作过于繁琐的程序让很大一部分用户敬而远之. 即使功能强大, 但是人们更愿意使用易于操作的软件. 近年流行起来的操作手势和逐渐趋于成 ...
随机推荐
- SOLID 原则
世纪的前几年里,“ Uncle Bob”Robert Martin 引入了用OOP 开发软件的五条原 则,其目的是设计出更易于维护的高质量系统.无论是设计新应用程序,还是重构现有基 本代码,这些 S ...
- poj 3468(线段树+lazy思想)
题目链接:http://poj.org/problem?id=3468 思路:如果直接去做,每次都更新到叶子节点,那必然会TLE,我们可以采用lazy的思想:没必要每次更新都更新到叶子节点,只要有一个 ...
- 知问前端——概述及jQuery UI
知问系统,是一个问答系统.主要功能:即会员提出问题,会员回答问题.目前比较热门的此类网站有:知乎http://www.zhihu.com.百度知道http://zhidao.baidu.com等.这里 ...
- spring_150803_component
实体类: package com.spring.model; public class DogPet { private int id; private String name; private in ...
- 李洪强iOS开发之OC[010] - 有参方法的声明实现和调用
// // main.m // 09 - 有参方法的声明实现和调用 // // Created by vic fan on 16/7/5. // Copyright © 2016年 李洪强. ...
- 对话框上右下角显示resize icon(可以拖动改变对话框的大小)(在WM_CREATE的时候,增加WS_THICKFRAME风格)
CStatusBar m_StatusBar; // 成员变量 // 全局变量 static UINT auIDStatusBar[] = { ID_SEPARATOR }; //在对话框类的WM_ ...
- java socket实现全双工通信
java socket实现全双工通信 单工.半双工和全双工的定义 如果在通信过程的任意时刻,信息只能由一方A传到另一方B,则称为单工. 如果在任意时刻,信息既可由A传到B,又能由B传A,但只能由一个方 ...
- 【解惑】让人头疼的"相等"关系
Java中判断相等关系一般有两种手段:(1) “==”关系操作符 (2) equals()方法. 显然,基本数据类型变量之间只能用"==".而对象之间两种手段都是合法的.但是有很 ...
- CentOS下判断自己的VPS是OpenVZ的还是Xen的
一般来说,VPS的虚拟化技术,有Xen.OpenVZ.Xen HVM和VMware这几种,那么,如何判断自己的VPS是基于哪种虚拟化技术的呢? 1.执行:ls /proc/命令,一般Xen的VPS,/ ...
- 关于请求添加HttpRequestHeader
WebClient w = new WebClient(); w.Headers.Add(HttpRequestHeader.Accept, "application/json") ...