java threadlocal 详解_Java基础进阶之ThreadLocal详解

ThreadLocal

基本在项目开发中基本不会用到, 但是面试官是比较喜欢问这类问题的;所以还是有必要了解一下该类的功能与原理的.

ThreadLocal是什么

ThreadLocal

是一个将在多线程中为每一个线程创建单独的变量副本的类; 当使用ThreadLocal来维护变量时, ThreadLocal

会为每个线程创建单独的变量副本, 避免因多线程操作共享变量而导致的数据不一致的情况;

ThreadLocal类用在哪些场景

一般来说, ThreadLocal

在实际工业生产中并不常见, 但是在很多框架中使用却能够解决一些框架问题; 比如Spring中的事务、Spring 中 作用域 Scope

为 Request的Bean

使用ThreadLocal来解决.

ThreadLocal使用方法

1、将需要被多线程访问的属性使用ThreadLocal变量来定义; 下面以网上多数举例的DBConnectionFactory类为例来举例

import java.sql.Connection;

import java.sql.DriverManager;

import java.sql.SQLException;

public class DBConnectionFactory {

private static final ThreadLocal dbConnectionLocal = new ThreadLocal() {

@Override

protected Connection initialValue() {

try {

return DriverManager.getConnection("", "", "");

} catch (SQLException e) {

e.printStackTrace();

}

return null;

}

};

public Connection getConnection() {

return dbConnectionLocal.get();

}

}

这样在Client获取Connection的时候, 每个线程获取到的Connection都是该线程独有的, 做到Connection的线程隔离; 所以并不存在线程安全问题

ThreadLocal如何实现线程隔离

1、主要是用到了Thread对象中的一个ThreadLocalMap类型的变量threadLocals, 负责存储当前线程的关于Connection的对象, 以 dbConnectionLocal

这个变量为Key, 以 新建的Connection

对象为Value; 这样的话, 线程第一次读取的时候如果不存在就会调用 ThreadLocal

的 initialValue

方法创建一个Connection对象并且返回;

具体关于为线程分配变量副本的代码如下:

public T get() {

Thread t = Thread.currentThread();

ThreadLocalMap map = getMap(t);

if (map != null) {

ThreadLocalMap.Entry e = map.getEntry(this);

if (e != null) {

@SuppressWarnings("unchecked")

T result = (T)e.value;

return result;

}

}

return setInitialValue();

}

1、首先获取当前线程对象 t

, 然后从线程 t

中获取到 ThreadLocalMap

的成员属性 threadLocals

2、如果当前线程的 threadLocals

已经初始化(即不为 null

) 并且存在以当前ThreadLocal对象为Key的值, 则直接返回当前线程要获取的对象(本例中为Connection);

3、如果当前线程的 threadLocals

已经初始化(即不为 null

)但是不存在以当前ThreadLocal对象为Key的的对象, 那么重新创建一个Connection对象, 并且添加到当前线程的threadLocals Map中,并返回

4、如果当前线程的 threadLocals

属性还没有被初始化, 则重新创建一个ThreadLocalMap对象, 并且创建一个Connection对象并添加到ThreadLocalMap对象中并返回。

如果存在则直接返回很好理解, 那么对于如何初始化的代码又是怎样的呢?

private T setInitialValue() {

T value = initialValue();

Thread t = Thread.currentThread();

ThreadLocalMap map = getMap(t);

if (map != null)

map.set(this, value);

else

createMap(t, value);

return value;

}

1、首先调用我们上面写的重载过后的 initialValue

方法, 产生一个Connection对象

2、继续查看当前线程的 threadLocals

是不是空的, 如果ThreadLocalMap已被初始化, 那么直接将产生的对象添加到ThreadLocalMap中, 如果没有初始化, 则创建并添加对象到其中;

那么我们看过代码之后就很清晰的知道了为什么ThreadLocal能够实现变量的多线程隔离了; 其实就是用了Map的数据结构给当前线程缓存了, 要使用的时候就从本线程的threadLocals对象中获取就可以了, key就是当前线程;

当然了在当前线程下获取当前线程里面的Map里面的对象并操作肯定没有线程并发问题了, 当然能做到变量的线程间隔离了;

现在我们知道了ThreadLocal到底是什么了, 又知道了如何使用ThreadLocal以及其基本实现原理了是不是就可以结束了呢? 其实还有一个问题就是ThreadLocalMap是个什么对象, 为什么要用这个对象呢?

ThreadLocalMap对象是什么

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值