Java并发多线程编程——ThreadLocal(线程本地存储)

Posted 小志的博客

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Java并发多线程编程——ThreadLocal(线程本地存储)相关的知识,希望对你有一定的参考价值。

一、ThreadLocal的理解

  • ThreadLocal属于java.lang包;
  • ThreadLocal,很多地方叫线程本地变量,也有一些地方叫线程本地存储,ThreadLocal的作用是提供线程内的局部变量,这种变量在线程的生命周期内起作用,减少同一个线程内多个函数或组件之间一些公共变量的传递的复杂度;
  • 当使用ThreadLocal维护变量时,ThreadLocal为每个使用该变量的线程提供独立的变量副本。所以每一个线程都可以独立地改变自己的副本,而不会影响其它线程所对应的副本;
  • 在JDK5.0中,ThreadLocal已经支持泛型,该类的类名已经变为ThreadLocal;

二、ThreadLocal类中常用的方法

在这里插入图片描述

  • void set(T value) 设置当前线程的线程局部变量的值
  • T get() 该方法返回当前线程所对应的线程局部变量
  • void remove() 将当前线程局部变量的值删除,目的是为了减少内存的占用
  • T initialValue() 返回该线程局部变量的初始值,该方法是一个protected的方法,显然是为了让子类覆盖而设计的。

三、 ThreadLocalMap的理解

  • 每个线程中都有一个自己的ThreadLocalMap类对象,可以将线程自己的对象保持到其中,各管各的,线程可以正确的访问到自己的对象;
  • 将一个公用的ThreadLocal静态实例作为key,将不同对象的引用保存到不同线程的ThreadLocalMap中,然后在线程执行的各处通过这个静态ThreadLocal实例的get()方法取得自己线程保存的那个对象,避免了将这个对象作为参数传递的麻烦;
  • ThreadLocalMap其实就是线程里面的一个属性,它在Thread类中定义ThreadLocal.ThreadLocalMap ThreadLocals =null;

四、ThreadLocal实现每个线程管理各自的变量示例

1、代码,第一个线程设置睡眠时间1秒钟,第二个线程设置睡眠时间0.5秒钟,为了方便查看结果。

package com.xz.thread.ThreadLocal;

/**
 * @description: ThreadLocal实现每个线程管理各自的变量示例
 * @author: xz
 * @create: 2021-05-28 21:27
 */
public class Demo {

    //实例化ThreadLocal,并初始化值为0
    private ThreadLocal<Integer> count =new ThreadLocal(){
        @Override
        protected Integer initialValue() {
            return new Integer(0);
        }
    };

    //获取值的方法,值每次加1并返回
    public int getNextValue(){
        Integer value=count.get();
        value++;
        count.set(value);
        return value;
    }

    //主方法测试
    public static void main(String[] args) {
        Demo d =new Demo();
        //第一个线程
        new Thread(new Runnable() {
            @Override
            public void run() {
                while(true){
                    System.out.println(Thread.currentThread().getName()+"  value="+d.getNextValue());
                    try {
                        Thread.sleep(1000);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
            }
        }).start();

        //第二个线程
        new Thread(new Runnable() {
            @Override
            public void run() {
                while(true){
                    System.out.println(Thread.currentThread().getName()+"  value="+d.getNextValue());
                    try {
                        Thread.sleep(500);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
            }
        }).start();

    }
}

2、运行main函数,输出结果如下:
在这里插入图片描述
3、结论:

  • ThreadLocal为每个使用该变量的线程提供独立的变量副本。所以每一个线程都可以独立地改变自己的副本,而不会影响其它线程所对应的副本;
  • 简单理解:每个线程中都有一个自己的ThreadLocalMap类对象,可以将线程自己的对象保持到其中,各管各的,线程可以正确的访问到自己的对象;

五、ThreadLocal在使用应用中的场景示例

1、代码示例

package com.xz.thread.ThreadLocal;

/**
 * @description:
 * @author: xz
 * @create: 2021-05-28 22:26
 */
public class Test {
    private final static ThreadLocal<User> threadLocal = new ThreadLocal<User>();

    //设置当前用户
    public void setCurrentUser(User user) {
        threadLocal.set(user);
    }

    //本地线程中取当前用户
    public void getCurrentSystemUser() {
        User user = threadLocal.get();
        if (null == user) {
           //执行代码
            ......
        }
    }
}

以上是关于Java并发多线程编程——ThreadLocal(线程本地存储)的主要内容,如果未能解决你的问题,请参考以下文章

Java并发编程:深入剖析ThreadLocal (总结)

Java并发机制--ThreadLocal线程本地变量(转)

如何实现springMVC的多线程并发?

如何实现springMVC的多线程并发?

多线程:线程相关类

Java并发编程:ThreadLocal