当前位置: 代码迷 >> 综合 >> 7.17 线程:ThreadLocal
  详细解决方案

7.17 线程:ThreadLocal

热度:94   发布时间:2023-11-21 10:50:35.0

线程:ThreadLocal

      • 简介
      • 测试

简介

  1. 在多线程环境下,每个线程都有自己的数据。一个线程使用自己的局部变量比使用全局变量好,因为局部变量只有线程自己能看见,不会影响其他线程。
  2. ThreadLocal能够放一个线程级别的变量,其本身能够被多个线程共享使用,并且又能够达到线程安全的目的。说白了,ThreadLocal就是想在多线程环境下去保证成员变量的安全,常用的方法,就是get/set/initialValue()方法。
  3. JDK建议ThreadLocal定义为private static
  4. ThreadLocal最常用的地方就是为每个线程绑定一个数据库连接,HTTP请求,用户身份信息等,这样一个线程的所有调用到的方法都可以非常方便地访问这些资源。
    (1)Hibernate的Session工具类HibernateUtil
    (2)通过不同的线程对象设置Bean属性,保证各个线程Bean对象的独立性。

测试

  1. 基本使用方法
    code:
/*** ThreadLocal:每个线程自身的存储本地、局部区域* get/set/initValue* @author dxt**/
public class ThreadLocalTest01 {
    //创建一个线程空间, 每个线程都在里面有一个只有自己可以访问的"保险箱"//public static ThreadLocal<Integer> threadLocal = new ThreadLocal<Integer>();//2. 更改线程空间的初始值,要重写initialValue()方法public static ThreadLocal<Integer> threadLocal = new ThreadLocal<Integer>(){
    protected Integer initialValue(){
    return 200;	//初始值由null变为200}};public static void main(String[] args){
    //1. 打印 主线程 的初始值, 因为是Integer而不是int,所以会打印null,而不是0System.out.println(Thread.currentThread().getName() + "--" + threadLocal.get());//3. 设置初始化值threadLocal.set(100);System.out.println(Thread.currentThread().getName() + "--" + threadLocal.get());//4. 在main线程外,建立新的线程,两个线程间的值互不影响new Thread(new MyRun()).start();//5. 每个线程在ThreadLocal内有自己独立的空间new Thread(new MyRun()).start();}/*** 静态内部类* @author dxt**/public static class MyRun implements Runnable{
    public void run(){
    threadLocal.set((int)(Math.random()*100));System.out.println(Thread.currentThread().getName() + "--" + threadLocal.get());}}
}

result:
res1
2. 每个线程有自己的存储区域
code:

/*** 每个线程有自己的存储区域* @author dxt**/
public class ThreadLocalTest02 {
    //创建线程空间public static ThreadLocal<Integer> threadLocal = new ThreadLocal<Integer>(){
    protected Integer initialValue(){
    return 1;	//将数据初始化为1,可以认为每个线程都有一个属于自己的1}};public static void main(String[] args){
    //建立5个线程for(int i=0; i<5; i++){
    new Thread(new MyRun()).start();}}public static class MyRun implements Runnable{
    public void run(){
    Integer left = threadLocal.get();System.out.println(Thread.currentThread().getName() + " 得到了"+ left+"个苹果");threadLocal.set(left-1);System.out.println(Thread.currentThread().getName() + " 还剩下"+ threadLocal.get()+"个苹果");}}
}

result:
res2
3. 分析上下文
code:

/*** 分析ThreadLocal的上下文, 环境* @author dxt**/
public class ThreadLocalTest03 {
    //创建线程空间public static ThreadLocal<Integer> threadLocal = new ThreadLocal<Integer>(){
    protected Integer initialValue(){
    return 1;	//将数据初始化为1,可以认为每个线程都有一个属于自己的1}};public static void main(String[] args){
    new Thread(new MyRun()).start();}public static class MyRun implements Runnable{
    public MyRun(){
    threadLocal.set(100);	//是对main线程进行更改//输出调用MyRun()构造函数的线程的信息System.out.println(Thread.currentThread().getName()+"--"+threadLocal.get());}public void run(){
    System.out.println(Thread.currentThread().getName()+"--"+threadLocal.get());}}
}

result:
res3
4. InheritableThreadLocal
code:

/*** InheitableThreadLocal:继承上下文环境的数据,复制一份数给子线程,在子线程中可以更改* 但不影响原数据 * @author dxt**/
public class ThreadLocalTest04 {
    public static ThreadLocal<Integer> threadLocal = new InheritableThreadLocal<Integer>();public static void main(String[] args){
    threadLocal.set(2);System.out.println(Thread.currentThread().getName() + " " + threadLocal.get());new Thread(new Runnable(){
    public void run(){
    	//若是ThreadLocal会是nullSystem.out.println(Thread.currentThread().getName() + " " + threadLocal.get());}}).start();}
}

result:
res4

  相关解决方案