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 ...
随机推荐
- rest-assured : Restful API 测试利器 - 真正的黑盒单元测试(跟Spring-Boot更配哦,更新至spring-boot1.4.1)
{ "Author":"tomcat and jerry", "URL" :"http://www.cnblogs.com/tom ...
- 多个插件依赖不同版本jQuery问题解决案例
<script src="../../../js/jquery-1.3.2.min.js" type="text/javascript">< ...
- 一个login
login 1.获取提交表单,保存到变量中.2.判断用户密码是否正确,利用Model类.3.验证用户是否激活.3.判断用户是否记住登录状态,是的话,将其用cookie和session分别保存.没有的话 ...
- YisouSpider你想搞死我的服务器吗?
在1分钟666次请求中,你占了445次,你大爷的想干啥呢? 42.156.254.30 - - [03/Feb/2016:11:46:00 +0800] "GET /thread-22063 ...
- Jmeter在linux上运行(命令行运行Jmeter)
1.下载安装 http://jmeter.apache.org/download_jmeter.cgi Jmeter官网下载 linux下应使用tgz包,下载 Binaries apache-jme ...
- freeCodeCamp:Seek and Destroy
金克斯的迫击炮! 实现一个摧毁(destroyer)函数,第一个参数是待摧毁的数组,其余的参数是待摧毁的值. 当你完成不了挑战的时候,记得开大招'Read-Search-Ask'. 这是一些对你有帮助 ...
- Maven 整合 spring profile实现多环境自动切换
Maven 整合 spring profile实现多环境自动切换 时间:2014-03-19 15:32来源:Internet 作者:Internet 点击:525次 profile主要用在项目多环境 ...
- iOS遍历相册中的图片
//获取相册的所有图片 - (void)reloadImagesFromLibrary { self.images = [[NSMutableArray alloc] init]; dispatch_ ...
- Java 第22章 mySQy
下列都是关系型数据库(在数据库中存在行.列) oracle: Oracle公司的产品(被sun公司收购) 中大型项目使用.银行系统.政府办公系统 9i/10g/11g sql server: 微软公司 ...
- iOS 应用中有页面加载gif动画,从后台进入前台时就消失了
解决办法: 在Appdelegate.m 里面有一个从后台进入前台所响应的方法,可以在该方法里post 一个通知,在加载动画里的页面接受通知,响应一定的方法即可 #pragma -mark 当程序进入 ...