Java代码质量改进之:使用ThreadLocal维护线程内部变量
在上文中,《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高质量代码编写方面的技巧,请联系我们哦。
Java代码质量改进之:使用ThreadLocal维护线程内部变量的更多相关文章
- [改善Java代码]不使用stop方法停止线程
线程启动完毕后,在运行可能需要终止,Java提供的终止方法只有一个stop,但是不建议使用此方法,因为它有以下三个问题: (1)stop方法是过时的 从Java编码规则来说,已经过时的方式不建议采用. ...
- Java并发(二十):线程本地变量ThreadLocal
ThreadLocal是一个本地线程副本变量工具类. 主要用于将私有线程和该线程存放的副本对象做一个映射,各个线程之间的变量互不干扰,在高并发场景下,可以实现无状态的调用,特别适用于各个线程依赖不同的 ...
- Java中的闪光点:ThreadLocal是线程Thead的局部变量,可替代同步机制的设计,值得学习和研究
线程局部变量ThreadLocal,是Java支持的一种线程安全机制,目的是解决多线程的并发问题. 具体来讲,就是多个线程访问该实例对象的变量时,该实例对象将其存储为键值对的形式,保证各个线程(键)分 ...
- 使用ThreadLocal在线程内部传递数据
最近在项目中使用到了JDK提供的线程池,遇到了在多线程环境下在线程内部共享数据的问题 使用ThreadLocal 来解决线程内部共享数据的问题 定义BO package com.unicom.uclo ...
- java线:辛格尔顿隐藏ThreadLocal实现线程数据共享
效果图分享: A和B需要共享同一线程,还有一组的相同A和B共享还有一组线程,两组相互之间不受影响. 代码: package cn.itcast.lesson6; import java.util.Ra ...
- Java代码质量改进之:同步对象的选择
在Java中,让线程同步的一种方式是使用synchronized关键字,它可以被用来修饰一段代码块,如下: synchronized(被锁的同步对象) { // 代码块:业务代码 } 当synchro ...
- Java 200+ 面试题补充 ThreadLocal 模块
让我们每天都有进步,老王带你打造最全的 Java 面试清单,认真把一件事做到极致. 本文是前文<Java 最常见的 200+ 面试题>的第一个补充模块. 1.ThreadLocal 是什么 ...
- java笔记--用ThreadLocal管理线程,Callable<V>接口实现有返回值的线程
用ThreadLocal管理线程,Callable<V>接口实现有返回值的线程 ThreadLocal在我的笔记"关于线程同步"的第5种方式里面有介绍,这里就不多说了. ...
- Java ThreadLocal (Java代码实战-006)
ThreadLocal解决什么问题 由于 ThreadLocal 支持范型,如 ThreadLocal< StringBuilder >,为表述方便,后文用 变量 代表 ThreadLoc ...
随机推荐
- css怎么让页面上的内容不能被选中
body{ -webkit-user-select:none; -moz-user-select:none; -ms-user-select:none; user-se ...
- ssh-keygen -t rsa -b 4096 -C "邮箱"
ssh-keygen -t rsa -b 4096 -C "邮箱":这条命令的目的是为了让本地机器ssh登录远程机器上的GitHub账户无需输入密码.将这条命令分解: 1.ssh- ...
- java 持有对象 ListIterator用法
package ch07; import java.io.*; import java.util.Iterator; import java.util.LinkedList; import java. ...
- poj3579 二分套二分
和poj3685类似,都是二分答案然后在判断时再二分 这题的内层二分可以用stl代替 /* 二分套二分,思路:升序排序数据,先二分答案x进行判断,判断时枚举每个元素,二分找到和其之差小于等于x的所有值 ...
- Django项目部署在Linux下以进程方式启动
Django项目部署在Linux下以进程方式启动 这是一篇关于如何在linux下,以后台进程的方式运行服务,命令改改基本上就通用了. 开发完Django项目后,需要把项目部署到linux环境下.当然, ...
- SpringMVC MongoDB之“基本文档查询(Query、BasicQuery)”
一.简介 spring Data MongoDB提供了org.springframework.data.mongodb.core.MongoTemplate对MongoDB的CRUD的操作,上一篇我 ...
- Myeclipse调试模式下自动提示变量值设置
1.Window->Preferences->Java->Editor->Hovers 将[Variable Values]选择即可,如果第一个[Combined Hover] ...
- Android使用帧动画内存溢出解决方法
Android使用帧动画内存溢出解决方法https://blog.csdn.net/daitu_liang/article/details/52336015https://blog.csdn.net/ ...
- WCF客户端从服务器下载数据
1.打开VS选择控制台项目新建一个解决方案Server,然后添加两个类库Contract和Service. 2.在Contract中添加一个接口IFileDownload using System; ...
- POJ 2139 Six Degrees of Cowvin Bacon (Floyd)
题意:如果两头牛在同一部电影中出现过,那么这两头牛的度就为1, 如果这两头牛a,b没有在同一部电影中出现过,但a,b分别与c在同一部电影中出现过,那么a,b的度为2.以此类推,a与b之间有n头媒介牛, ...