你知道threadlocal的应用场景是怎样的吗?你知道threadlocal使用方式吗?下面的文章就是要给大家介绍这两个方面的内容,一起来了解一下吧。
首先我们来讲一下threadlocal应用场景,为了可以将threadlocal应用场景讲清楚,下面就以一个框架作为示例。
Spring的事务管理器通过AOP切入业务代码,在进入业务代码之前,会根据相应的事务管理器提取出相应的事务对象。
假如说,事务管理器是DataSourceTransactionManager,那么就会从DataSource当中获得一个连接对象,经过一定的包装过后,将它保存在ThreadLocal当中。
除此之外,Spring也对DataSource进行了包装,重写了其中的getConnection()方法,又或者是说,这个方法的返回将会由Spring来控制。
这样的话,Spring就可以使得线程内多次获取到的Connection对象是同一个。
那么,这里有一个问题了,放在threadlocal里面这是为什么呢?
这主要是因为Spring在AOP后并不可以向应用程序传递參数。
应用程序的每一个业务代码都是事先定义好的,Spring并不会要求在业务代码的入口參数中必须编写Connection的入口參数。
这个时候,Spring选择了threadlocal。
通过threadlocal保证连接对象始终在线程内部,也就是不管在什么时候都可以拿到。
那么这样的话,Spring就会非常的清楚在什么时候回收这个连接,也就是很明白,什么时候从threadlocal当中删除这个元素。
那么,从Spring事务管理器的设计上面可以看出,Spring利用threadlocal得到了一个非常好的设计思路。
与此同时它在设计的时候,也十分的清楚threadlocal中元素应该在什么时候删除。
所以,简单地觉得ThreadLocal尽量使用在一个全局的设计上,而不是说,一种打补丁的间接方法。
对于这些基本应用场景你都了解了吗?
那么下面,就一起来看一下具体的示例吧。
定义一个类用于存放静态的ThreadLocal对象,通过多个线程并行地对ThreadLocal对象进行set、get操作,并将值进行打印。
代码:
public class ThreadLocalTest { static class ResourceClass { public final static ThreadLocal < String > RESOURCE_1 = new ThreadLocal < String > (); public final static ThreadLocal < String > RESOURCE_2 = new ThreadLocal < String > (); } static class A { public void setOne(String value) { ResourceClass.RESOURCE_1.set(value); } public void setTwo(String value) { ResourceClass.RESOURCE_2.set(value); } } static class B { public void display() { System.out.println(ResourceClass.RESOURCE_1.get() + ":" + ResourceClass.RESOURCE_2.get()); } } public static void main(String[] args) { final A a = new A(); final B b = new B(); for (int i = 0; i < 15; i++) { final String resouce1 = "线程-" + I; final String resouce2 = " value = (" + i + ")"; new Thread() { public void run() { try { a.setOne(resouce1); a.setTwo(resouce2); b.display(); } finally { ResourceClass.RESOURCE_1.remove(); ResourceClass.RESOURCE_2.remove(); } } }.start(); } } }
测试结果
线程-6: value = (6)
线程-9: value = (9)
线程-0: value = (0)
线程-10: value = (10)
线程-12: value = (12)
线程-14: value = (14)
线程-11: value = (11)
线程-3: value = (3)
线程-5: value = (5)
线程-13: value = (13)
线程-2: value = (2)
线程-4: value = (4)
线程-8: value = (8)
线程-7: value = (7)
线程-1: value = (1)
可以很明显的看得出来,输出的线程顺序并不是最初定义线程的顺序。
理论上可以表示,多线程应当是并发运行的。
但是,依旧能够保持每一个线程里面的值是相应的,也就表示,这些值已经达到了线程私有的目的。
好了对于threadlocal应用场景及使用方式就给大家介绍到这里了,更多threadlocal常见问题,欢迎继续关注奇Q工具网来进行了解哦。
推荐阅读: