Java多线程10:ThreadLocal的作用及使用
ThreadLocal的作用
从上一篇对于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
Java多线程10:ThreadLocal的作用及使用的更多相关文章
- java多线程10:并发工具类CountDownLatch、CyclicBarrier和Semaphore
在JDK的并发包(java.util.concurrent下)中给开发者提供了几个非常有用的并发工具类,让用户不需要再去关心如何在并发场景下写出同时兼顾线程安全性与高效率的代码. 本文分别介绍Coun ...
- java多线程--------深入分析 ThreadLocal 内存泄漏问题
前言 ThreadLocal 的作用是提供线程内的局部变量,这种变量在线程的生命周期内起作用,减少同一个线程内多个函数或者组件之间一些公共变量的传递的复杂度.但是如果滥用ThreadLocal,就可能 ...
- java 多线程(threadlocal)
package com.example; import java.util.Random; public class App { public static class MyRunnable1 imp ...
- Java多线程之 ThreadLocal
一.什么是ThreadLocal? 顾名思义它是local variable(线程局部变量).它的功用非常简单,就是为每一个使用该变量的线程都提供一个变量值的副本,是每一个线程都可以独立地改变自己的副 ...
- Java多线程基础-ThreadLocal
感谢原文作者:Yuicon 原文链接:https://segmentfault.com/a/1190000016705955 序 在多线程环境下,访问非线程安全的变量时必须进行线程同步,例如使用 sy ...
- java多线程学习-ThreadLocal
为了凑字,把oracle文档里介绍ThreadLocal抄过来 public class ThreadLocal<T> extends Object This class provides ...
- Java多线程:ThreadLocal
一.ThreadLocal基础知识 ThreadLocal是线程的一个本地化对象,或者说是局部变量.当工作于多线程中的对象使用ThreadLocal维护变量时,ThreadLocal为每个使用该变量的 ...
- java 多线程 day06 threadLocal
import java.util.HashMap;import java.util.Map;import java.util.Random; /** * Created by chengtao on ...
- java 多线程 :ThreadLocal 共享变量多线程不同值方案;InheritableThreadLocal变量子线程中自定义值,孙线程可继承
ThreadLocal类的使用 变量值的共享可以使用public static变量的形式,所有的线程都是用同一个public static变量.如果想实现每一个线程都有自己的值.该变量可通过Thr ...
随机推荐
- iOStextFiled判断输入长度
个人在开发当中发现在用textField的代理方法 -(BOOL)textField:(UITextField *)textField shouldChangeCharactersInRange:(N ...
- VS2012智能提示消失的解决方法
1.点击电脑左下角的“开始菜单”->"所有程序"->Microsoft Visual Studio 2012->Visual Studio Tools->V ...
- vim的撤销和恢复操作以及匹配当前单词操作
今天顺便看了一下vim的一点命令,记录一下 1.撤销上一次操作和恢复上一次操作: u → undo <C-r> → redo 2.搜索上一个单词和下一个单词 * 和 #: 匹配光标当前所在 ...
- 把页面上的图表导出为pdf文件,分享一种请求下载文件的方法
最近客户提出一个需求,就是把页面上的图表导出为pdf文件. 找了很多资料.终于有了点头绪.最主要是参考了HighCharts的做法.http://www.hcharts.cn/ 实现原理:把页面图表的 ...
- python代码优化---就喜欢细节
地址:http://www.codeproject.com/Tips/829060/Python-Code-Optimizations-Part-One 转发过来保存一下.喜欢精雕细琢,编程才有乐趣. ...
- Linux下修改mysql密码
# /etc/init.d/mysql stop# mysqld_safe --user=mysql --skip-grant-tables --skip-networking &# mysq ...
- DEV GridControl双击行事件
首先,需要将gridview1.OptionsBehavior.Editable设为false //双击行弹出nodeDetail信息 private void gridView1_MouseDown ...
- centOS升级python3.5
CentOS自带的版本是2.7.5 目前在看廖老师的教学,他给的新版本是3以上了,果断升级到最新的Python版本 (windows下面多线程里面有点问题没解决,所以才换到linux下继续学习) 一 ...
- 编译PCL Tutorial文件
1.PCL Tutorial是使用SPHINX编译而成的. 2.安装Python2.7,从官方网站上下载(Portable Python测试未成功,待研究). 3.安装setuptools,安装成功会 ...
- Android adb常用指令
Android 调试桥(adb)是多种用途的工具,该工具可以帮助你你管理设备或模拟器 的状态. 可以通过下列几种方法加入adb: 在设备上运行shell命令 通过端口转发来管理模拟器或设备 从模拟器或 ...