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的作用及使用的更多相关文章

  1. java多线程10:并发工具类CountDownLatch、CyclicBarrier和Semaphore

    在JDK的并发包(java.util.concurrent下)中给开发者提供了几个非常有用的并发工具类,让用户不需要再去关心如何在并发场景下写出同时兼顾线程安全性与高效率的代码. 本文分别介绍Coun ...

  2. java多线程--------深入分析 ThreadLocal 内存泄漏问题

    前言 ThreadLocal 的作用是提供线程内的局部变量,这种变量在线程的生命周期内起作用,减少同一个线程内多个函数或者组件之间一些公共变量的传递的复杂度.但是如果滥用ThreadLocal,就可能 ...

  3. java 多线程(threadlocal)

    package com.example; import java.util.Random; public class App { public static class MyRunnable1 imp ...

  4. Java多线程之 ThreadLocal

    一.什么是ThreadLocal? 顾名思义它是local variable(线程局部变量).它的功用非常简单,就是为每一个使用该变量的线程都提供一个变量值的副本,是每一个线程都可以独立地改变自己的副 ...

  5. Java多线程基础-ThreadLocal

    感谢原文作者:Yuicon 原文链接:https://segmentfault.com/a/1190000016705955 序 在多线程环境下,访问非线程安全的变量时必须进行线程同步,例如使用 sy ...

  6. java多线程学习-ThreadLocal

    为了凑字,把oracle文档里介绍ThreadLocal抄过来 public class ThreadLocal<T> extends Object This class provides ...

  7. Java多线程:ThreadLocal

    一.ThreadLocal基础知识 ThreadLocal是线程的一个本地化对象,或者说是局部变量.当工作于多线程中的对象使用ThreadLocal维护变量时,ThreadLocal为每个使用该变量的 ...

  8. java 多线程 day06 threadLocal

    import java.util.HashMap;import java.util.Map;import java.util.Random; /** * Created by chengtao on ...

  9. java 多线程 :ThreadLocal 共享变量多线程不同值方案;InheritableThreadLocal变量子线程中自定义值,孙线程可继承

      ThreadLocal类的使用 变量值的共享可以使用public static变量的形式,所有的线程都是用同一个public static变量.如果想实现每一个线程都有自己的值.该变量可通过Thr ...

随机推荐

  1. some things

    ////html[1]/body[1]/div[9]/div[1]/div[1]/div[1]/ul/li  截取规则 Articles/Article[1]:选取属于Articles子元素的第一个A ...

  2. 一点一滴学shell

    1. 获取shell脚本的名称 ${BASH_SOURCE-$0} 2. 获取shell脚本的路径 dirname "${BASH_SOURCE-$0}" 这个路径不一定是脚本的真 ...

  3. 在windows 下安装启动redis

    在windows环境下安装 redis这个需要在github中下载开源代码,https://github.com/mythz/redis-windows 下载最近的zip包然后 解压到任意一个盘符中进 ...

  4. mysq安装以及修改密码

    安装版MySQL是不能一键安装的,下载下来是压缩包,解压后只要进行相关配置就可以正常使用: 文章主要是记录一下,以防自己忘记: 1.首先在mysql官网--http://dev.mysql.com/d ...

  5. 多线程Server client

    项目结构 项目设计 客户端同时大量请求服务端,服务端多线程处理连接,并发序列化获得客户端发送的数据,并做出处理. IClients package simple.socket; import java ...

  6. vuex2.0.0爬坑记录 -- mutations的第一个参数state不能解构

    今天在学习vuex的过程中,遇到了一个很困扰人的问题,最终利用vuex的状态快照工具logger解决了问题. 问题是这样的,我在子组件中使用了mapState()函数来将状态映射至子组件中,使子组件能 ...

  7. css3之多列

                                             

  8. 再次完善了 WASPCN for Matlab

    前段时间有多个网友询问在64位Matlab中如何使用WASPCN(水和蒸汽性质计算软件)的方法,一直没能给出解决方案. 最近自己有个项目也需要在64位Matlab中如何使用WASPCN(水和蒸汽性质计 ...

  9. 最小生成树算法——Kruskal算法

    #include<stdio.h> #include<algorithm> #include<windows.h> using namespace std; str ...

  10. SVN的服务器端用户权限配置

    第一:用户的配置 SVN和apache整合的话,用户可以直接使用htpasswd dav_svn.passwd_file_address USERNAME来配置. 而账户的管理可以用dav_svn.a ...