ThreadLocal的一点个人理解

来源:互联网 发布:windows linux 大数据 编辑:程序博客网 时间:2024/06/03 14:55

1、先说ThreadLocal的实现原理,从实现的原理我们就能搞清楚他的应用场景。
我们先来看ThreadLocal中的域,如下:

private final int threadLocalHashCode = nextHashCode();private static AtomicInteger nextHashCode =        new AtomicInteger();private static final int HASH_INCREMENT = 0x61c88647;

可以看到只有threadLocalHashCode 是ThreadLocal的实例变量,nextHashCode ,HASH_INCREMENT 是静态变量,可以看到三个变量都是int型的,那么,我们调用set()方法时传递的对象保存在哪里呢?我们再来看一下set()方法。

 public void set(T value) {        Thread t = Thread.currentThread();        ThreadLocalMap map = getMap(t);        if (map != null)            map.set(this, value);        else            createMap(t, value);    }

map.set(this, value); 可以看到,这个map是以ThreadLocal为键,将我们传递的对象放到map中去的。
那么这个map又是什么来路,我们可以看getMap(Thread t);

ThreadLocalMap getMap(Thread t) {        return t.threadLocals;    }

这里可以看到,原来map是Thread类的一个域。
于是我们可以看我们set方法设置的对象其实是保存在了ThreadLocal所在线程的一个ThreadLocalMap 中了,这个Map以ThreadLocal为键。
总结来说就是:每个Thread都有一个ThreadLocalMap的域,用来保存ThreadLocal和Object的映射。
2、我们可以假设这种应用场景,比如说我们需要在每个线程都维持一个对象,那么我们可能会这样设计

class Thread implements Runnable {    Object obj;}

那要是如果我们需要维持N个对象呢,那么我们可以用一个Object数组

class Thread implements Runnable {    Object obj[];}

其实Object数组就是一种key为整型,值为Object的Map结构

class Thread implements Runnable {    Map<Integer,Object>;}

JDK只是用ThreadLocal作为键而已,我们用Integer。
3、应用场景:数据库连接

private static ThreadLocal<Connection> connectionHolder= new ThreadLocal<Connection>() {public Connection initialValue() {    return DriverManager.getConnection(DB_URL);}};public static Connection getConnection() {return connectionHolder.get();}

注意:DriverManager.getConnection(DB_URL);这里每次返回的是一个内容一样,但是占用不同内存的Connection。
网上很多人说,ThreadLocal不是用来解决共享对象的多线程访问问题的,其实也可以看做是,就上面的例子而言,Connection不是线程安全的,那么,我们给每个线程都设置一个内容一样的Connection,线程安全的问题不就解决了吗。这是一种以“空间换取时间“的做法。

0 0
原创粉丝点击