ThreadLocal源码分析及其应用

ThreadLocal在很多地方都有使用过,今天看看它是如何来实现的。还是先通过一个小的例子看看用法,然后再分析其源码。

import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

/**
 * 
 * ThreadLocal用法示例
 *
 */
class ThreadTask implements Runnable {
    // ThreadLocal实例
    ThreadLocal<String> locals = new ThreadLocal<String>();

    @Override
    public void run() {
        if (locals.get() == null) {
            locals.set(Thread.currentThread().getName() + "aaa");
        }
        System.out.println(locals.get());
    }
}

public class ThreadLocalDemo {
    public static void main(String args[]) {
        // 线程池
        ExecutorService exec = Executors.newFixedThreadPool(4);
        for(int i=0;i<4;i++){
            ThreadTask threadTask = new ThreadTask();
            exec.submit(threadTask);
        }
    }
}

ThreadLocal有两个关键的方法:get()和set()。
public T get() {
        // 获取当前线程
        Thread t = Thread.currentThread();
        // 获取ThreadLocalMap对象
        ThreadLocalMap map = getMap(t);
        if (map != null) {
            // this就是ThreadLocal实例对象
            ThreadLocalMap.Entry e = map.getEntry(this);
            if (e != null)
                return (T)e.value;
        }
        // 如果不存在就初始化
        return setInitialValue();
}

private T setInitialValue() {
        // 默认返回null值
        T value = initialValue();
        Thread t = Thread.currentThread();
        ThreadLocalMap map = getMap(t);
        if (map != null)
            // this表示的是ThreadLocal实例对象
            map.set(this, value);
        else
            // new ThreadLocalMap(),这里t就是当前线程
            createMap(t, value);
        return value;
}
public T get() {
        Thread t = Thread.currentThread();
        // 每个线程都有这样的一个ThreadLocalMap对象
        ThreadLocalMap map = getMap(t);
        if (map != null) {
            // 然后通过ThreadLocal实例对象来查找其value值
            ThreadLocalMap.Entry e = map.getEntry(this);
            if (e != null)
                return (T)e.value;
        }
        return setInitialValue();
}

所以从源码上就可以看出,ThreadLocal内部有一个ThreadLocalMap对象,每个线程都有这个对象ThreadLocalMap,这个map的key值是ThreadLocal实例对象,value就是存储的值。

在Spring 获取Connection时,它是这样在DataSourceUtils中应用的。

public static Connection doGetConnection(DataSource dataSource) throws SQLException {
        // 这里调用TransactionSynchronizationManager.getResource()方法
        // TransactionSynchronizationManager中resource是ThreadLocal类型
        ConnectionHolder conHolder = (ConnectionHolder) TransactionSynchronizationManager.getResource(dataSource);
        if (conHolder != null && (conHolder.hasConnection() || conHolder.isSynchronizedWithTransaction())) {
            conHolder.requested();
            if (!conHolder.hasConnection()) {
                conHolder.setConnection(dataSource.getConnection());
            }
            return conHolder.getConnection();
        }
        return con;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值