ThreadLoacl的作用及使用
2016-04-14 15:44
267 查看
ThreadLocal的作用
从上一篇对于ThreadLocal的分析来看,可以得出结论:ThreadLocal不是用来解决共享对象的多线程访问问题的,通过ThreadLocal的set()方法设置到线程的ThreadLocal.ThreadLocalMap里的是是线程自己要存储的对象,其他线程不需要去访问,也是访问不到的。各个线程中的ThreadLocal.ThreadLocalMap以及ThreadLocal.ThreadLocal中的值都是不同的对象。
至于为什么要使用ThreadLocal,不妨这么考虑这个问题。Java Web中,写一个Servlet:
我在一个普通JavaBean内想拿到这个HttpServletRequest,但是无法通过参数传递的方式:
这时候怎么办?第一个解决方案,Servlet类中定义一个全局的HttpServletRequest,至于怎么定义就随便了,可以定义成静态的,也可以定义成非静态的但是对外提供setter/getter,然后operateRequest()方法每次都取这个全局的HttpServletRequest就可以了。
不否认,这是一种可行的解决方案,但是这种解决方案有一个很大的缺点:竞争。既然HttpServletRequest是全局的,那势必要引入同步机制来保证线程安全性,引入同步机制意味着牺牲响应给用户的时间----这在注重与用户之间响应的Java Web中是难以容忍的。
所以,我们引入ThreadLocal,既然ThreadLocal.ThreadLocalMap是线程独有的,别的线程访问不了也没必要访问,那我们通过ThreadLocal把HttpServletRequest设置到线程的ThreadLocal.ThreadLocalMap里面去不就好了?这样,在一次请求中哪里需要用到HttpServletRequest,就使用ThreadLocal的get()方法就把这个HttpServletRequest给取出来了,是不是一个很好的解决方案呢?
ThreadLocal使用
忘记上面那个复杂的问题,我们来看一下ThreadLocal的简单使用,首先ThreadLocal肯定是全局共享的:
写一个线程往ThreadLocal里面塞值:
写个main函数,启动三个ThreadLocalThread:
看一下运行结果:
看到每个线程的里都有自己的String,并且互不影响----因为绝对不可能出现数字重复的情况。用一个ThreadLocal也可以多次set一个数据,set仅仅表示的是线程的ThreadLocal.ThreadLocalMap中table的某一位置的value被覆盖成你最新设置的那个数据而已,对于同一个ThreadLocal对象而言,set后,table中绝不会多出一个数据。
ThreadLocal再总结
上一篇文章的最后有对ThreadLocal的工作原理进行总结,这里对ThreadLocal再次进行一个总结:
1、ThreadLocal不是集合,它不存储任何内容,真正存储数据的集合在Thread中。ThreadLocal只是一个工具,一个往各个线程的ThreadLocal.ThreadLocalMap中table的某一位置set一个值的工具而已
2、同步与ThreadLocal是解决多线程中数据访问问题的两种思路,前者是数据共享的思路,后者是数据隔离的思路
3、同步是一种以时间换空间的思想,ThreadLocal是一种空间换时间的思想
4、ThreadLocal既然是与线程相关的,那么对于Java Web来讲,ThreadLocal设置的值只在一次请求中有效,是不是和request很像?因为request里面的内容也只在一次请求有效,对比一下二者的区别:
(1)ThreadLocal只能存一个值,一个Request由于是Map形式的,可以用key-value形式存多个值
(2)ThreadLocal一般用在框架,Request一般用在表示层、Action、Servlet
从上一篇对于ThreadLocal的分析来看,可以得出结论:ThreadLocal不是用来解决共享对象的多线程访问问题的,通过ThreadLocal的set()方法设置到线程的ThreadLocal.ThreadLocalMap里的是是线程自己要存储的对象,其他线程不需要去访问,也是访问不到的。各个线程中的ThreadLocal.ThreadLocalMap以及ThreadLocal.ThreadLocal中的值都是不同的对象。
至于为什么要使用ThreadLocal,不妨这么考虑这个问题。Java Web中,写一个Servlet:
public class Servlet extends HttpServlet { protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { this.doGet(request, response); } protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { } }
我在一个普通JavaBean内想拿到这个HttpServletRequest,但是无法通过参数传递的方式:
public class OperateRequest { public String operateRequest() { return null; } }
这时候怎么办?第一个解决方案,Servlet类中定义一个全局的HttpServletRequest,至于怎么定义就随便了,可以定义成静态的,也可以定义成非静态的但是对外提供setter/getter,然后operateRequest()方法每次都取这个全局的HttpServletRequest就可以了。
不否认,这是一种可行的解决方案,但是这种解决方案有一个很大的缺点:竞争。既然HttpServletRequest是全局的,那势必要引入同步机制来保证线程安全性,引入同步机制意味着牺牲响应给用户的时间----这在注重与用户之间响应的Java Web中是难以容忍的。
所以,我们引入ThreadLocal,既然ThreadLocal.ThreadLocalMap是线程独有的,别的线程访问不了也没必要访问,那我们通过ThreadLocal把HttpServletRequest设置到线程的ThreadLocal.ThreadLocalMap里面去不就好了?这样,在一次请求中哪里需要用到HttpServletRequest,就使用ThreadLocal的get()方法就把这个HttpServletRequest给取出来了,是不是一个很好的解决方案呢?
ThreadLocal使用
忘记上面那个复杂的问题,我们来看一下ThreadLocal的简单使用,首先ThreadLocal肯定是全局共享的:
public class Tools { public static ThreadLocal<String> t1 = new ThreadLocal<String>(); }
写一个线程往ThreadLocal里面塞值:
public class ThreadLocalThread extends Thread { private static AtomicInteger ai = new AtomicInteger(); public ThreadLocalThread(String name) { super(name); } public void run() { try { for (int i = 0; i < 3; i++) { Tools.t1.set(ai.addAndGet(1) + ""); System.out.println(this.getName() + " get value--->" + Tools.t1.get()); Thread.sleep(200); } } catch (InterruptedException e) { e.printStackTrace(); } } }
写个main函数,启动三个ThreadLocalThread:
public static void main(String[] args) throws Exception { ThreadLocalThread a = new ThreadLocalThread("ThreadA"); ThreadLocalThread b = new ThreadLocalThread("ThreadB"); ThreadLocalThread c = new ThreadLocalThread("ThreadC"); a.start(); b.start(); c.start(); }
看一下运行结果:
ThreadA get value--->1 ThreadC get value--->2 ThreadB get value--->3 ThreadB get value--->4 ThreadC get value--->6 ThreadA get value--->5 ThreadC get value--->8 ThreadA get value--->7 ThreadB get value--->9
看到每个线程的里都有自己的String,并且互不影响----因为绝对不可能出现数字重复的情况。用一个ThreadLocal也可以多次set一个数据,set仅仅表示的是线程的ThreadLocal.ThreadLocalMap中table的某一位置的value被覆盖成你最新设置的那个数据而已,对于同一个ThreadLocal对象而言,set后,table中绝不会多出一个数据。
ThreadLocal再总结
上一篇文章的最后有对ThreadLocal的工作原理进行总结,这里对ThreadLocal再次进行一个总结:
1、ThreadLocal不是集合,它不存储任何内容,真正存储数据的集合在Thread中。ThreadLocal只是一个工具,一个往各个线程的ThreadLocal.ThreadLocalMap中table的某一位置set一个值的工具而已
2、同步与ThreadLocal是解决多线程中数据访问问题的两种思路,前者是数据共享的思路,后者是数据隔离的思路
3、同步是一种以时间换空间的思想,ThreadLocal是一种空间换时间的思想
4、ThreadLocal既然是与线程相关的,那么对于Java Web来讲,ThreadLocal设置的值只在一次请求中有效,是不是和request很像?因为request里面的内容也只在一次请求有效,对比一下二者的区别:
(1)ThreadLocal只能存一个值,一个Request由于是Map形式的,可以用key-value形式存多个值
(2)ThreadLocal一般用在框架,Request一般用在表示层、Action、Servlet
相关文章推荐
- leetcode——34——Search for a Range
- unity_Editor自定义窗口顶部添加小图标
- Windows下如何杀掉进程或占用相关端口号的进程
- php yaf框架扩展实践五——数据层
- Enlisting multiple 1-phase aware participants in the same transaction
- 【JS】:JS实现网页计算器
- Android 主流网络请求框架 Volley
- R -读取excel
- sql之left join、right join、inner join的区别
- POJ1386 Play on Words
- 【MySQL初学】篇一
- maven pom.xml 配置
- Spring + Sping MVC +Hibernate 整合
- Spring MVC 入门示例讲解
- 网页浏览远程网络视频
- 循环引用的案例
- Css3 box-sizing属性
- gitlab的搭建
- centos 6.5安装快速安装部署nginx-1.9.4
- Python一日一练17----哈希查找