首先,ThreadLocal 不是用来解决共享对象的多线程访问问题的,一般情况下,通过ThreadLocal.set() 到线程中的对象是该线程自己使用的对象,其他线程是不需要访问的,也访问不到的。各个线程中访问的是不同的对象。 
另外,说ThreadLocal使得各线程能够保持各自独立的一个对象,并不是通过ThreadLocal.set()来实现的,而是通过每个线程中的new 对象 的操作来创建的对象,每个线程创建一个,不是什么对象的拷贝或副本。通过ThreadLocal.set()将这个新创建的对象的引用保存到各线程的自己的一个map中,每个线程都有这样一个map,执行ThreadLocal.get()时,各线程从自己的map中取出放进去的对象,因此取出来的是各自自己线程中的对象,ThreadLocal实例是作为map的key来使用的。 
如果ThreadLocal.set()进去的东西本来就是多个线程共享的同一个对象,那么多个线程的ThreadLocal.get()取得的还是这个共享对象本身,还是有并发访问问题。

之前对于线程和方法的理解有些偏差,竟稀里糊涂的认为一个线程就是一个方法,一个方法就是一个线程。尤其在理解ThreadLocal执行原理的时候,更是晕乎 
(ThreadLocal把当前线程作为key,来维护管理一个可变的对象,在某一个方法里面set值,在后面的某个方法调用里面get值,如果一个方法就是一个线程,那set和get使用的key就不是同一个了,set进去的值get是拿不出来了) 
现在可以肯定,一个线程由一个方法启动,一个线程里面可以有多个方法,并不是每个方法都是一个线程。

看下面的实例代码,主方法里面调用一个方法,并启动了一个线程,子线程里面调用了一个方法,该方法中又调用了另外一个方法,看看他们的线程名称都是什么?

public class TestThread extends Thread{public TestThread(String name){super(name);}@Overridepublic void run() {System.out.println("启动一个子线程,线程名称为:"+Thread.currentThread().getName());//直接调用方法
            runSub();}public void runSub(){System.out.println("在run方法里调用,线程名称为:"+Thread.currentThread().getName());//直接调用方法
            runSubToSub();}public void runSubToSub(){System.out.println("在 runSub里面被调用,线程名称为:"+Thread.currentThread().getName());}public static void main(String[] args) {System.out.println("当前主线程名称为:"+Thread.currentThread().getName());//直接调用方法
            mainSub();//启动一个线程new TestThread("我是子线程001").start();}public static void mainSub(){System.out.println("直接在主方法里被调用,线程名称为:"+Thread.currentThread().getName());}
}

看看输出结果:

当前主线程名称为:main 直接在主方法里被调用,

线程名称为:main 启动一个子线程,

线程名称为:我是子线程001 在run方法里调用,

线程名称为:我是子线程001 在 runSub里面被调用,

线程名称为:我是子线程001

总之,ThreadLocal不是用来解决对象共享访问问题的,而主要是提供了保持对象的方法和避免参数传递的方便的对象访问方式。归纳了两点: 
1。每个线程中都有一个自己的ThreadLocalMap类对象,可以将线程自己的对象保持到其中,各管各的,线程可以正确的访问到自己的对象。 
2。将一个共用的ThreadLocal静态实例作为key,将不同对象的引用保存到不同线程的ThreadLocalMap中,然后在线程执行的各处通过这个静态ThreadLocal实例的get()方法取得自己线程保存的那个对象,避免了将这个对象作为参数传递的麻烦。 
当然如果要把本来线程共享的对象通过ThreadLocal.set()放到线程中也可以,可以实现避免参数传递的访问方式,但是要注意get()到的是那同一个共享对象,并发访问问题要靠其他手段来解决。但一般来说线程共享的对象通过设置为某类的静态变量就可以实现方便的访问了,似乎没必要放到线程中。 
ThreadLocal的应用场合,我觉得最适合的是按线程多实例(每个线程对应一个实例)的对象的访问,并且这个对象很多地方都要用到。

延伸:

http请求,到业务处理,再到响应的过程,是在一个线程里面的。 
对tomcat来说,每一个进来的请求(request)都需要一个线程,直到该请求结束。tomcat会维护一个线程池,每一个http请求,会从线程池中取出一个空闲线程。默认初始化75个线程,可以进行修改。

Tomcat处理HTTP请求源码分析(下)、我们发起的HTTP请求如何到达Servlet的、tomcat调优

转载于:https://www.cnblogs.com/lxl57610/p/8483784.html

一个请求方法是一个线程吗?不是!相关推荐

  1. 操作系统:为什么IO操作不占用CPU却会导致进程阻塞?Web服务器每接收一个请求都会创建一个新的线程吗?Tomcat服务器工作原理?

    为什么IO操作不占用CPU却会导致进程阻塞?Web服务器每接收一个请求都会创建一个新的线程吗?这两个问题在我学操作系统以前我都挺困惑的.现在我来尝试着解答一下. 1. 为什么IO操作不占用CPU却会导 ...

  2. php每一个请求会创建一个线程吗,实现一个线程池

    一.线程最主要的三个同步机制 1.信号量 2.互斥锁 3.条件变量 二.对三个同步机制分别实现一个包装类#ifdef LOCKER_H #define LOCKER_H #include #inclu ...

  3. 取消一个请求(Cancel)

    CANCEL请求,就像名字所说的,是用来取消客户端发起的上一个请求的. CANCEL请求UAS去终止上一个请求并且对上一个请求产生一个错误的应答.CANCEL对UAS已经给出终结应答的请求无效.所以, ...

  4. Django视图层:URL调度器、Django处理一个请求、URLconf在查找什么?URL:①path()路径、②路径转换器Path converter、③正则表达式组re_path()

    一.视图层The view layer Django 具有 "视图" 的概念,负责处理用户的请求并返回响应. 二.URL调度器URL dispatcher urlpattern:U ...

  5. HTTP请求方法介绍

          之前在https://blog.csdn.net/fengbingchun/article/details/85039308 中介绍过HTTP协议,在https://blog.csdn.n ...

  6. uni-app封装请求方法与api封装调用

    1.封装请求创建request.js文件,把一下内容根据自己的需求更改. //封装请求方法 //声明一个请求函数 const api_request=(url, method, parm)=>{ ...

  7. HTTP协议漫谈 - HTTP协议请求方法

    前言 在上一篇文章<HTTP协议漫谈 - HTTP协议历史和报文结构>中介绍了HTTP协议的历史和版本变化,以及HTTP协议报文的总体结构. 按照HTTP/1.1 RFC文档中的定义,HT ...

  8. 一个http请求就是一个线程吗,java的服务是每收到一个请求就新开一个线程来处理吗...

    一个http请求就是一个线程吗,java的服务是每收到一个请求就新开一个线程来处理吗 答案是:是,一个http请求,就是一个线程. https://blog.csdn.net/elvis_lfc/ar ...

  9. 笔试:当一个线程进入一个对象的一个synchronized方法后,其它线程是否可进入此对象的其它方法? ?(2nd)...

    当一个线程进入一个对象的一个synchronized方法后,其它线程是否可进入此对象的其它方法?(2nd) 日前在网上见到一道Java笔试试题,如题所述.给出的答案如下: 答:不能,一个对象的一个sy ...

最新文章

  1. 千万别说做过高并发!
  2. COBOL入门到精通
  3. Android下的动画
  4. flowJS源码个人分析
  5. 成功解决调用密钥报错4001 加密方式错误
  6. 某pl/sql培训练习题
  7. jQuery-DOM操作
  8. 美团笔试题——正则序列
  9. ps如何裁剪掉图片的不规则区域
  10. 运行3项目显示Module ‘“vue“‘ has no exported member ‘xxxx‘. Did you mean ‘Xxxx‘? TS2305: Module ‘“…/…/node_
  11. 计算机二级考风考纪主题班会,计算机二级C语言上机题库及答案(100套).doc
  12. 在Markdown文档中插入数学公式
  13. 博士入坑必读教材-A-Z博士(PhD)顺利毕业必读指南
  14. 【数据结构与算法】数据结构+算法=程序
  15. Linux应用:安装Nginx
  16. SmartFoxServer(SFS) 是什么?
  17. 利用支付宝Cookie监听订单实现个人支付宝收款实时回调
  18. 软件开发中的3P和1A
  19. 使用DTCPing工具解决MSDTC问题(新事务无法在指定的事务协调器中登记)
  20. 新颖且有价值的想法在哪里以及如何产生的?与产生相关的后颞叶和与执行控制相关的前额叶皮层的tDCS

热门文章

  1. linux系统运维面试题
  2. bootstrap 全局 CSS 样式
  3. Tom's Classes
  4. Oracle中判断空游标的方法
  5. 计算机基础教案(XP操作系统)
  6. django时间格式化加时区控制
  7. linux mount命令参数及用法详解
  8. HDU 5226 Tom and matrix(组合数学+Lucas定理)
  9. python requests的安装与简单运用
  10. 敏捷个人手机应用:如何使用时中法目标