threadLocal使用详解

参考:https://www.zhihu.com/question/341005993

1. threadLocal是什么

我们的Spring是单例的,在多线程访问的时候会出现线程安全问题。
解决办法

  • 不要再成员位置定义成员变量
  • 如果非要定义成员变量,在类上用@Scope("prototype")=========================每次获取Bean的时候会有一个新的实例,当请求数越多,性能会降低,因为每次回创建新的实例。
  • 使用ThreadLocal

ThreadLocal:很多地方叫做线程本地变量,也有些地方叫做线程本地存储,其实意思差不多。
ThreadLocal:在每个线程中对该变量会创建一个副本,即每个线程内部都会有一个该变量,且在线程内部任何地方都可以使用,线程之间互不影响,这样一来就不存在线程安全问题,也不会严重影响程序执行性能。

ThreadLocal提供的几个方法:

public T get() { }                  用于获取当前线程所对应的线程局部变量
public void set(T value) { }        用于设置当前线程的线程局部变量的值
public void remove() { }            用来移除当前线程局部变量的值
protected T initialValue() { }      返回该线程局部变量的初始值,该方法是一个protected的方法,显然是为了让子类覆盖而设计的。
                                    这个方法是一个延迟调用方法,在线程第1次调用get()或set(Object)时才执行,并且仅执行1次。ThreadLocal中的缺省实现直接返回一个null。
package test;

public class ThreadLocalTest {

    static ThreadLocal<String> localVar = new ThreadLocal<>();

    static void print(String str) {
        //打印当前线程中本地内存中本地变量的值
        System.out.println(str + " :" + localVar.get());
        //清除本地内存中的本地变量
        localVar.remove();
    }

    public static void main(String[] args) {
        Thread t1  = new Thread(new Runnable() {
            @Override
            public void run() {
                //设置线程1中本地变量的值
                localVar.set("localVar1");
                //调用打印方法
                print("thread1");
                //打印本地变量
                System.out.println("after remove : " + localVar.get());
            }
        });

        Thread t2  = new Thread(new Runnable() {
            @Override
            public void run() {
                //设置线程1中本地变量的值
                localVar.set("localVar2");
                //调用打印方法
                print("thread2");
                //打印本地变量
                System.out.println("after remove : " + localVar.get());
            }
        });

        t1.start();
        t2.start();
    }
}


原文地址:https://www.cnblogs.com/itlihao/p/14969768.html