(1)  Threadlocal定义:

当使用ThreadLocal维护变量时,ThreadLocal为每个使用该变量的线程提供独立的变量副本,所以每一个线程都可以独立地改变自己的副本,而不会影响其它线程所对应的副本。

(2)  ThreadLocal类接口很简单,只有4个方法,我们先来了解一下:

  • void set(Object value)设置当前线程的线程局部变量的值。
  • public Object get()该方法返回当前线程所对应的线程局部变量。
  • public void remove()将当前线程局部变量的值删除,目的是为了减少内存的占用,该方法是JDK 5.0新增的方法。需要指出的是,当线程结束后,对应该线程的局部变量将自动被垃圾回收,所以显式调用该方法清除线程的局部变量并不是必须的操作,但它可以加快内存回收的速度。
  • protected Object initialValue()返回该线程局部变量的初始值,该方法是一个protected的方法,显然是为了让子类覆盖而设计的。这个方法是一个延迟调用方法,在线程第1次调用get()或set(Object)时才执行,并且仅执行1次。ThreadLocal中的缺省实现直接返回一个null。

在JDK5.0中,ThreadLocal已经支持泛型,该类的类名已经变为ThreadLocal<T>。API方法也相应进行了调整,新版本的API方法分别是void set(T value)、T get()以及T initialValue()。

(3) ThreadLocal是如何实现的:

ThreadLocal是如何做到为每一个线程维护变量的副本的呢?其实实现的思路很简单:在ThreadLocal类中有一个Map,用于存储每一个线程的变量副本。

(4)ThreadLocal会为每一个线程提供一个独立的变量副本,从而隔离了多个线程对数据的访问冲突。因为每一个线程都拥有自己的变量副本,从而也就没有必要对该变量进行同步了。ThreadLocal提供了线程安全的共享对象,在编写多线程代码时,可以把不安全的变量封装进ThreadLocal。

(5)ThreadLocal的使用场景(这个很重要)

ThreadLocal不是用来解决对象共享访问问题的,而主要是提供了线程保持对象的方法和避免参数传递的方便的对象访问方式,ThreadLocal的应用场合,最适合的是按线程多实例(每个线程对应一个实例)的对象的访问,并且这个对象很多地方都要用到。

我说明一种使用ThreadLocal的情况。设置你使用了Servlet调用一些业务方法。你有个需求即:为记录日志每一个请求该servlet的过程生成一个唯一的业务标识并把它传递到业务方法中。
一个解决方法是把这个业务标识作为一个参数传递给每一个方法。但这不是不念旧恶好的解决方案因为代码是冗余且没有必要的。
要解决它,就要用到ThreadLocal,你生成一个业务标识并把它设置到ThreadLocal中,在这之后,任何一个业务方法,这个servlet调能从这个变量中访问业务标识。
这个Servlet可能服务于不止一个请求。因为每个请求都是一个线程,因此业务标识对每个线程是唯一的(局部),且对线程的整个执行过程是可见的(全局)

(6)   ThreadLocal 例子

Conneciton代表一个连接,一个线程内,都用一个; 不同的线程用不同的connection 实例;

public class Connection {
private int conId; public Connection(int id) {
// TODO Auto-generated constructor stub
} public int getConId() {
return conId;
} public void setConId(int conId) {
this.conId = conId;
}
}

  

TestClass的实例只要一个,但是 con 是每个线程有一个副本
import java.util.Random;

public class TestClass implements Runnable {
private ThreadLocal<Connection> con = new ThreadLocal<Connection>() {
public Connection initialValue(){
return new Connection(0);
}
}; public static void main(String[] args)
{
TestClass t1 = new TestClass();
new Thread(t1,"t1").start();
new Thread(t1,"t2").start();
} public void run() {
Random i = new Random();
int value = i.nextInt(100);
System.out.println("before set, current thread value " + Thread.currentThread()
+ ":" + value); con.set(new Connection(value)); System.out.println("after set, current thread value " + Thread.currentThread()
+ ":" + value); try {
Thread.sleep(3000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
System.out.println("Finally current thread value " + Thread.currentThread()
+ ":" + value);
}
}

输出结果:

before set, current thread value Thread[t1,5,main]:71
after set, current thread value Thread[t2,5,main]:12
after set, current thread value Thread[t1,5,main]:71
Finally current thread value Thread[t2,5,main]:12
Finally current thread value Thread[t1,5,main]:71

一 ThreadLocal的更多相关文章

  1. ThreadLocal简单理解

    在java开源项目的代码中看到一个类里ThreadLocal的属性: private static ThreadLocal<Boolean> clientMode = new Thread ...

  2. Android线程管理之ThreadLocal理解及应用场景

    前言: 最近在学习总结Android的动画效果,当学到Android属性动画的时候大致看了下源代码,里面的AnimationHandler存取使用了ThreadLocal,激起了我很大的好奇心以及兴趣 ...

  3. Threadlocal使用Case

    Threadlocal能够为每个线程分配一份单独的副本,使的线程与线程之间能够独立的访问各自副本.Threadlocal 内部维护一个Map,key为线程的名字,value为对应操作的副本. /** ...

  4. 多线程映射工具——ThreadLocal

    ThreadLocal相当于一个Map<Thread, T>,各线程使用自己的线程对象Thread.currentThread()作为键存取数据,但ThreadLocal实际上是一个包装了 ...

  5. ThreadLocal 工作原理、部分源码分析

    1.大概去哪里看 ThreadLocal 其根本实现方法,是在Thread里面,有一个ThreadLocal.ThreadLocalMap属性 ThreadLocal.ThreadLocalMap t ...

  6. ThreadLocal<T>的是否有设计问题

    一.吐槽 ThreadLocal<T>明显是.NET从JAVA中来的一个概念,但是这种设计是否出现了问题. 很明显,在JAVA中threadLocal直接是Thread的成员,当然随着th ...

  7. 理解ThreadLocal —— 一个map的key

    作用: 当工作于多线程中的对象使用ThreadLocal维护变量时,threadLocal为每个使用该变量的线程分配一个独立的变量副本. 接口方法: protected T initialValue( ...

  8. JavaSe:ThreadLocal

    JDK中有一个ThreadLocal类,使用很方便,但是却很容易出现问题.究其原因, 就是对ThreadLocal理解不到位.最近项目中,出现了内存泄漏的问题.其中就有同事在使用ThreadLocal ...

  9. 0041 Java学习笔记-多线程-线程池、ForkJoinPool、ThreadLocal

    什么是线程池 创建线程,因为涉及到跟操作系统交互,比较耗费资源.如果要创建大量的线程,而每个线程的生存期又很短,这时候就应该使用线程池了,就像数据库的连接池一样,预先开启一定数量的线程,有任务了就将任 ...

  10. ThreadLocal 源码剖析

    ThreadLocal是Java语言提供的用于支持线程局部变量的类.所谓的线程局部变量,就是仅仅只能被本线程访问,不能在线程之间进行共享访问的变量(每个线程一个拷贝).在各个Java web的各种框架 ...

随机推荐

  1. Oracle视图传递参数

    在Oracle里,视图不像存储过程和函数一样,可以定义输入参数,但我们可以变个方式,使用程序包来实现. oracle package: oracle package是oracle包,是一组相关过程.函 ...

  2. SAP 定价

    近几天做门店团购销售订单上传SAP接口程序,SO创建测试过程中, 遇到定价问题,同事在定价过程的增强过不了. VOFM 了解到定价过程是个非常复杂的环节,此处出现程序处理过程中ZMP0定价条件下的价格 ...

  3. [从jQuery看JavaScript]-匿名函数与闭包(Anonymous Function and Closure)

    http://blog.csdn.net/natineprince/article/details/4759533   jQuery片段: (function(){ //这里忽略jQuery所有实现 ...

  4. node-sass 安装失败的解决措施[转]

    转自:http://blog.csdn.net/nzb329/article/details/51935236 在编译一个项目的时候,一直报错 后来发现是因为node-sass没有装成功, 最终的解决 ...

  5. python基础1 ---python简介

    python基础 一.python前言 1.什么是编程语言 编程语言是程序员与计算机之间沟通的介质. 2.编程语言的分类 机器语言:机器语言是用二进制代码表示的计算机能直接识别和执行的一种机器指令的集 ...

  6. foreign key

    http://sevenseacat.net/2015/02/24/add_foreign_key_gotchas.html https://robots.thoughtbot.com/referen ...

  7. 【leetcode刷题笔记】Word Search

    Given a 2D board and a word, find if the word exists in the grid. The word can be constructed from l ...

  8. SpringCloud之服务提供和服务调用的搭建

    pom文件: <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3 ...

  9. java入门了解12

    1.SequenceInputStream序列流:能将其他输入流的串联 用处:读完第一个再去读第二个输入流 用法:构造方法:SequenceInputStream(InputStream s1,Inp ...

  10. html5制作坦克大战

    全部html5都采用绘图技术完成.坦克是画出来的.(坦克,子弹,墙,水,草坪) 首先我们画出坦克. 坦克是两边两个矩形,中间一个大矩形,矩形了有一个圆,还有一根线. 画出坦克的思路是以坦克的左上角为参 ...