相信读者在网上也看了很多关于ThreadLocal的资料,很多博客都这样说:ThreadLocal为解决多线程程序的并发问题提供了一种新的思路;ThreadLocal的目的是为了解决多线程访问资源时的共享问题。如果你也这样认为的,那现在给你10秒钟,清空之前对ThreadLocal的错误的认知!
看看JDK中的源码是怎么写的:
This class provides thread-local variables. These variables differ from their normal counterparts in that each thread that accesses one (via its {@code get} or {@code set} method) has its own, independently initialized copy of the variable. {@code ThreadLocal} instances are typically private static fields in classes that wish to associate state with a thread (e.g., a user ID or Transaction ID).
翻译过来大概是这样的(英文不好,如有更好的翻译,请留言说明):
ThreadLocal类用来提供线程内部的局部变量。这种变量在多线程环境下访问(通过get或set方法访问)时能保证各个线程里的变量相对独立于其他线程内的变量。ThreadLocal实例通常来说都是private static类型的,用于关联线程和线程的上下文。
可以总结为一句话:ThreadLocal的作用是提供线程内的局部变量,这种变量在线程的生命周期内起作用,减少同一个线程内多个函数或者组件之间一些公共变量的传递的复杂度。
举个例子,我出门需要先坐公交再做地铁,这里的坐公交和坐地铁就好比是同一个线程内的两个函数,我就是一个线程,我要完成这两个函数都需要同一个东西:公交卡(北京公交和地铁都使用公交卡),那么我为了不向这两个函数都传递公交卡这个变量(相当于不是一直带着公交卡上路),我可以这么做:将公交卡事先交给一个机构,当我需要刷卡的时候再向这个机构要公交卡(当然每次拿的都是同一张公交卡)。这样就能达到只要是我(同一个线程)需要公交卡,何时何地都能向这个机构要的目的。
有人要说了:你可以将公交卡设置为全局变量啊,这样不是也能何时何地都能取公交卡吗?但是如果有很多个人(很多个线程)呢?大家可不能都使用同一张公交卡吧(我们假设公交卡是实名认证的),这样不就乱套了嘛。现在明白了吧?这就是ThreadLocal设计的初衷:提供线程内部的局部变量,在本线程内随时随地可取,隔离其他线程。
(1)ThreadContext
这个类提供线程局部变量。这些变量与普通的变量不同,因为每个访问一个线程的线程(通过其get或set方法)都有自己的独立初始化变量的副本。
ThreadLocal实例通常是希望将状态与线程关联的类中的私有静态字段(例如:一个用户ID或事务ID)。每个线程都对线程本地变量的副本有一个隐式引用,
只要线程还活着,ThreadLocal实例就可以访问;在一个线程消失之后,所有线程本地实例的副本都将被垃圾收集(除非存在其他引用)。
常用的方法有:
1 public class ThreadLocal<T> { 2 3 //设置属性 4 5 public void set(T value) { 6 Thread t = Thread.currentThread(); 7 ThreadLocalMap map = getMap(t); 8 if (map != null) 9 map.set(this, value);10 else11 createMap(t, value);12 }13 14 //获取属性15 16 public T get() {17 Thread t = Thread.currentThread();18 ThreadLocalMap map = getMap(t);19 if (map != null) {20 ThreadLocalMap.Entry e = map.getEntry(this);21 if (e != null)22 return (T)e.value;23 }24 return setInitialValue();25 }26 27 //获取线程的 ThreadLocal.ThreadLocalMap28 29 ThreadLocalMap getMap(Thread t) {30 return t.threadLocals;31 }32 33 }34 35 //新建一个线程本地的localMap36 37 void createMap(Thread t, T firstValue) {38 t.threadLocals = new ThreadLocalMap(this, firstValue);39 }
(2)使用例子:连接、会话如下:
1 private static ThreadLocal<Connection> connectionHolder 2 = new ThreadLocal<Connection>() { 3 public Connection initialValue() { 4 return DriverManager.getConnection(DB_URL); 5 } 6 }; 7 8 public static Connection getConnection() { 9 return connectionHolder.get();10 }
1 private static final ThreadLocal threadSession = new ThreadLocal(); 2 3 public static Session getSession() throws InfrastructureException { 4 Session s = (Session) threadSession.get(); 5 try { 6 if (s == null) { 7 s = getSessionFactory().openSession(); 8 threadSession.set(s); 9 }10 } catch (HibernateException ex) {11 throw new InfrastructureException(ex);12 }13 return s;14 }
Atas ialah kandungan terperinci ThreadLocal解决多线程程序的实例. Untuk maklumat lanjut, sila ikut artikel berkaitan lain di laman web China PHP!