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. textField和textView限制输入条件

    以下两法方法都是实现textfield和textView的代理方法  需要先遵循代理 一:textField限制只能输入数字和小数点 且小数点后只能保留两位 小数点前最多5位 - (BOOL)text ...

  2. 【转】Nginx服务器详细配置含注释

    #使用的用户和组 user www www; #指定工作衍生进程数(一般等于CPU的总核数或总核数的两倍) worker_processes 8; #指定错误日志存放的路径,错误日志的记录级别可为de ...

  3. python day2 列表的常用操作方法

    #创建列表方法一li = ['aa','bb','cc']方法二li = list(['aa','bb','cc'])print(li)返回 ['aa', 'bb', 'cc']----------- ...

  4. 用C语言关于学生管理系统的几种实现方法(一位数组,二维数组,指针,结构体)

    一位数组: #include <stdio.h> #include<string.h> #define N 5 void luru(float s[],int n); void ...

  5. Git常用

    创建本地库 mkdir [dirname] cd [dirname] git init 1.创建项目目录 2.进入目录 3.git初始化 [dirname]为自己取的文件夹名字,例如mkdir myd ...

  6. 解决Get请求的长度限制

    错误提示: HTTP Error 404.15 - Not Found The request filtering module is configured to deny a request whe ...

  7. PerconaXtraBackup --全备增备prepare restore

    Xtrabackup Xtrabackup包含两个主要的工具,即xtrabackup和innobackupex,二者区别如下:  • xtrabackup只能备份innodb和xtradb引擎表,而不 ...

  8. iOS-三方框架AFNetworking基本使用

    AFNetworking 是基于NSURLConnection, NSOperation开发的一款三方框架,主要用于处理一些关于网络请求上的业务,下文会简单介绍框架中经常使用的功能,如文件的上传,下载 ...

  9. Last non-zero Digit in N!(阶乘最后非0位)

    Last non-zero Digit in N! Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Jav ...

  10. Android中 int 和 String 互相转换的多种方法

    1 如何将字串 String 转换成整数 int? A. 有两个方法: 1). int i = Integer.parseInt([String]); 或 i = Integer.parseInt([ ...