在上文中,《Java代码质量改进之:同步对象的选择》,我们提出了一个场景:火车站有3个售票窗口,同时在售一趟列车的100个座位。我们通过锁定一个靠谱的同步对象,完成了上面的功能。

现在,让我们反过来,每个窗口负责一趟车。比如一号窗口就卖1号列车的票,二号窗口就卖2号列车的票。不过它们需要同时开始卖票。

一:ThreadLocal的最简应用

首先,既然是各卖各的火车了,那么,就不需要同步了。于是代码又回归到:

但是当前的代码肯定是不对的,每个线程访问的都是同一个火车的ticket,并且还会出现超售现象。要保证每new一个窗口出来,就有一趟自己的列车,我们就可以用到ThreadLocal对象了。

让我们首先替换掉ticket变量,改为:

然后,售票的代码改为:

虽然ticket依然是一个static变量,但是,运行程序你会发现,新起一个线程,不同的线程还是会拥有自己的ticket,不会互相干扰。也就是实现了每个窗口卖自己那趟车的目标。

二:ThreadLocal VS 实例变量

每一个程序员都应该是杠精。为什么,因为回过神来的我们发现,只要回到第一段代码中,把ticket中的static去掉,就能达到同样的目的:

试下上面的代码,是不是也能达到各卖各的目的?

我们是脑袋被门板挤了,才想出来一个TheadLocal这样的复杂方案吗?

如果单纯说上面的这段代码,是的。但是,还有很多的场合,是ThreadLocal的用武之处。比如,我们并不永远使用extends Thead的方式来写多线程,我们还可能用implements Runnable的方式来写多线程(ps:还有更多的写法哦),如下:

而在这种情况下,我们就不得不使用TheadLocal了,这里就不放出代码了,大家可以试一下。

甚至,更进一步的,我们是不是能够把ticket这个变量放进方法内部呢,如果放入方法

内部的话,我们同样也是必须要使用ThreadLocal才能达到实现目的,如下:

总之,简单来说:当要运行的代码本身不是很方便访问当前的线程实例的时候,就是ThreadLocal的用武之地。

三:ThreadLocal的应用场景

ThreadLocal有这样一些应用场景,比如连接池管理、会话管理等等。

在连接池的管理中,当我们需要获取一个连接,就应该为每一次获取给出不同的连接。在web应用中,请求是被线程池管理的,也就是说获取连接这个行为不是单线程行为,所以我们最好就要设计成不同的线程不能获取同一个连接,要保证能做到这样,就应该使用ThreadLocal了。

可能有人会表示,那不能设计成实例变量吗?答案是:不能。因为,在web应用中,线程都不是被我们自己管理的,所以,最佳的做法就是使用ThreadLocal。一个标准的做法如下:

最后作为补充,我们再来看看hibernate中ThreadLocal的应用:

      以下是广告时间:最课程(http://zuikc.com)正在招收Java就业班学员,如果你想学习更多的Java高质量代码编写方面的技巧,请联系我们哦。

转载于:https://www.cnblogs.com/luminji/p/9419292.html

Java代码质量改进之:使用ThreadLocal维护线程内部变量相关推荐

  1. java 内部thread_Java代码质量改进之:使用ThreadLocal维护线程内部变量

    在上文中,<Java代码质量改进之:同步对象的选择>,我们提出了一个场景:火车站有3个售票窗口,同时在售一趟列车的100个座位.我们通过锁定一个靠谱的同步对象,完成了上面的功能. 现在,让 ...

  2. [改善Java代码]不使用stop方法停止线程

    线程启动完毕后,在运行可能需要终止,Java提供的终止方法只有一个stop,但是不建议使用此方法,因为它有以下三个问题: (1)stop方法是过时的 从Java编码规则来说,已经过时的方式不建议采用. ...

  3. ThreadLocal应用-使用ThreadLocal做线程缓存变量池

    多线程环境下,或者web环境下,可以使用ThreadLocal做变量池用 import java.util.HashMap; import java.util.Map;public abstract ...

  4. js字符串如何拼接java代码_JS如何定义用字符串拼接的变量

    今天在写js的时候碰到了难题,我又一个页面需要生成很多的变量.但是变量的名称是根据参数的不同而区分的. 例如可能需要生成 date_1,date_2,datet_3... (后面的数字是根据参数来的) ...

  5. Java 200+ 面试题补充 ThreadLocal 模块

    让我们每天都有进步,老王带你打造最全的 Java 面试清单,认真把一件事做到极致. 本文是前文<Java 最常见的 200+ 面试题>的第一个补充模块. 1.ThreadLocal 是什么 ...

  6. Java:多线程(同步死锁、锁原子变量、线程通信、线程池)

    5,同步和死锁 5.1,线程同步 修饰一个代码块,被修饰的代码块称为同步语句块,其作用的范围是大括号{}括起来的代码,作用的对象是调用这个代码块的对象: 修饰一个方法,被修饰的方法称为同步方法,其作用 ...

  7. linux用于在固定时间间隔启动,按固定时间间隔在Linux环境中运行java代码

    主要分两步:一.在Linux环境中一直运行一个线程.二.如何控制java代码同时执行多个工作线程. 一.可以用Linux中的  nohup 命令,控制该线程就算在终端被关闭或者账户退出之后,继续在后台 ...

  8. Eclipse解决每次修改java代码或jsp代码服务器重启问题的解决办法

    1.面临的问题:     Eclipse有点非常不友好,就是不管我怎么修改Java代码,哪怕只有仅仅一行代码都需要重新启动,才能使修改代码生效.   由于我们项目较大,这点严重影响了我的工作效率,本文 ...

  9. JAVA线程本地变量ThreadLocal和私有变量的区别

    ThreadLocal并不是一个Thread,而是Thread的局部变量,也许把它命名为ThreadLocalVariable更容易让人理解一些. 所以,在Java中编写线程局部变量的代码相对来说要笨 ...

  10. Java高并发编程详解系列-线程上下文设计模式及ThreadLocal详解

    导语   在之前的分享中提到过一个概念就是线程之间的通信,都知道在线程之间的通信是一件很消耗资源的事情.但是又不得不去做的一件事情.为了保证多线程线程安全就必须进行线程之间的通信,保证每个线程获取到的 ...

最新文章

  1. Battery electric vehicles (BEVs) 快充技术
  2. 阿里巴巴发布AI养蜂系统
  3. Nginx+Keepalived+Proxy_Cache 配置高可用集群和高速缓存
  4. 基于Android设备的Kali Linux渗透测试教程第1章渗透测试
  5. Boost.Signals2 的多槽 hello world 示例
  6. 手把手教你把代码丢入github 中
  7. javascript一些底层方法总结及用法
  8. 应用程序无法正常启动(0xc000007b)错误的解决
  9. mybatis注解开发_快速搭建MyBatis开发环境(配置版+注解版)
  10. mysql报表慢_mysql慢查询日志报表工具mysqlsla
  11. laravel5.5 Auth门脸类认证
  12. 对拷 使用scp命令在两台linux上对拷文件或者文件夹
  13. VSCode 设置为 Monaco字体
  14. 窦志成:从微软到人大,只为做有温度的AI
  15. 【STM32】 STM32单片机IO引脚配置方式
  16. python中oserror_[python] 解决OSError:
  17. pytorch骚操作之梯度累加,变相增大batch size
  18. 搭建自己的dns服务器
  19. 微型计算机的软 硬件组成,微型计算机的软、硬件组成及主要性能指标
  20. 作业扣最少的分(要选好贪心目标)

热门文章

  1. 我的树莓派3配置脚本
  2. 创建 tomcat 服务的镜像
  3. 怎么使用Vegas制作炫彩灯光效果?
  4. 制作Camtasia 2020击键标记动画
  5. 性能爆表缺软件?M1版MacBook真不能装Win10吗
  6. Java并发编程笔记之ArrayBlockingQueue源码分析
  7. HDU 1711 Number Sequence (KMP)
  8. hdu5414(2015多校10)--CRB and String(字符串匹配)
  9. Objective-C学习笔记(十八)——对象方法和类方法的声明,定义及调用
  10. 第三方库之 - SDWebImage