文档章节

ThreadLocal

杨肥麻
 杨肥麻
发布于 2017/07/12 22:47
字数 702
阅读 1
收藏 0
点赞 0
评论 0

先强调一点:ThreadLocal不是用来解决共享变量问题的,它与多线程的并发问题没有任何关系。

1.基本概念?

当使用ThreadLocal维护变量时,ThreadLocal为每个使用该变量的线程提供独立的变量副本,所以每一个线程都可以独立地改变自己的副本,而不会影响其它线程所对应的副本。

2.threadLocal是如何做到为每一个线程维护变量的副本的呢?

在ThreadLocal类中有一个Map,用于存储每一个线程的变量副本,Map中元素的键为线程对象,而值对应线程的变量副本。我们自己就可以提供一个简单的实现版本。

SimpleThreadLocal 原理实现

  1. public class SimpleThreadLocal {  
  2.     private Map valueMap = Collections.synchronizedMap(new HashMap());  
  3.     public void set(Object newValue) {  
  4.                 //①键为线程对象,值为本线程的变量副本  
  5.         valueMap.put(Thread.currentThread(), newValue);  
  6.     }  
  7.     public Object get() {  
  8.         Thread currentThread = Thread.currentThread();  
  9.   
  10.                 //②返回本线程对应的变量  
  11.         Object o = valueMap.get(currentThread);   
  12.                   
  13.                 //③如果在Map中不存在,放到Map中保存起来  
  14.                if (o == null && !valueMap.containsKey(currentThread)) {  
  15.             o = initialValue();  
  16.             valueMap.put(currentThread, o);  
  17.         }  
  18.         return o;  
  19.     }  
  20.     public void remove() {  
  21.         valueMap.remove(Thread.currentThread());  
  22.     }  
  23.     public Object initialValue() {  
  24.         return null;  
  25.     }  
  26. }  

 ThreadLocal使用的例子:

  1. package com.baobaotao.basic;  
  2.   
  3. public class SequenceNumber {  
  4.        
  5.         //①通过匿名内部类覆盖ThreadLocal的initialValue()方法,指定初始值  
  6.     private static ThreadLocal<Integer> seqNum = new ThreadLocal<Integer>(){  
  7.         public Integer initialValue(){  
  8.             return 0;  
  9.         }  
  10.     };  
  11.        
  12.         //②获取下一个序列值  
  13.     public int getNextNum(){  
  14.         seqNum.set(seqNum.get()+1);  
  15.         return seqNum.get();  
  16.     }  
  17.       
  18.     public static void main(String[ ] args)   
  19.     {  
  20.           SequenceNumber sn = new SequenceNumber();  
  21.            
  22.          //③ 3个线程共享sn,各自产生序列号  
  23.          TestClient t1 = new TestClient(sn);    
  24.          TestClient t2 = new TestClient(sn);  
  25.          TestClient t3 = new TestClient(sn);  
  26.          t1.start();  
  27.          t2.start();  
  28.          t3.start();  
  29.     }     
  30.     private static class TestClient extends Thread  
  31.     {  
  32.         private SequenceNumber sn;  
  33.         public TestClient(SequenceNumber sn) {  
  34.             this.sn = sn;  
  35.         }  
  36.         public void run()  
  37.         {  
  38.                         //④每个线程打出3个序列值  
  39.             for (int i = 0; i < 3; i++) {  
  40.             System.out.println("thread["+Thread.currentThread().getName()+  
  41. "] sn["+sn.getNextNum()+"]");  
  42.             }  
  43.         }  
  44.     }  

执行结果:

thread[Thread-2] sn[1] 
thread[Thread-0] sn[1] 
thread[Thread-1] sn[1] 
thread[Thread-2] sn[2] 
thread[Thread-0] sn[2] 
thread[Thread-1] sn[2] 
thread[Thread-2] sn[3] 
thread[Thread-0] sn[3] 
thread[Thread-1] sn[3] 

可以看到,各个线程的longLocal值与stringLocal值是相互独立的,本线程的累加操作不会影响到其他线程的值,真正达到了线程内部隔离的效果。

3.使用场景

最常见的ThreadLocal使用场景为 用来解决数据库连接、Session管理等,那么接下来我们就看看spring事务中ThreadLocal的应用

4.总结

1、ThreadLocal能解决的问题,那肯定不是共享变量(多线程并发)问题,只是看起来有些像并发;像火车票、电影票这样的真正的共享变量的问题用ThreadLocal是解决不了的,同一时间,同一趟车的同一个座位,你敢用ThreadLocal来解决吗?

2、每个Thread维护一个ThreadLocalMap映射表,这个映射表的key是ThreadLocal实例本身,value是真正需要存储的Object

© 著作权归作者所有

共有 人打赏支持
杨肥麻
粉丝 1
博文 53
码字总数 30289
作品 0
深圳

暂无文章

Android 复制和粘贴功能

做了一回搬运工,原文地址:https://blog.csdn.net/kennethyo/article/details/76602765 Android 复制和粘贴功能,需要调用系统服务ClipboardManager来实现。 ClipboardManager mClipboardM...

她叫我小渝
27分钟前
0
0
拦截SQLSERVER的SSL加密通道替换传输过程中的用户名密码实现运维审计(一)

工作准备 •一台SQLSERVER 2005/SQLSERVER 2008服务 •SQLSERVER jdbc驱动程序 •Java开发环境eclipse + jdk1.8 •java反编译工具JD-Core 反编译JDBC分析SQLSERVER客户端与服务器通信原理 SQ...

紅顏為君笑
44分钟前
4
0
jQuery零基础入门——(六)修改DOM结构

《jQuery零基础入门》系列博文是在廖雪峰老师的博文基础上,可能补充了个人的理解和日常遇到的点,用我的理解表述出来,主干出处来自廖雪峰老师的技术分享。 在《零基础入门JavaScript》的时...

JandenMa
今天
0
0
linux mint 1.9 qq 安装

转: https://www.jianshu.com/p/cdc3d03c144d 1. 下载 qq 轻聊版,可在百度搜索后下载 QQ7.9Light.exe 2. 去wine的官网(https://wiki.winehq.org/Ubuntu) 安装 wine . 提醒网页可以切换成中...

Canaan_
今天
0
0
PHP后台运行命令并管理运行程序

php后台运行命令并管理后台运行程序 class ProcessModel{ private $pid; private $command; private $resultToFile = ''; public function __construct($cl=false){......

colin_86
今天
1
0
数据结构与算法4

在此程序中,HighArray类中的find()方法用数据项的值作为参数传递,它的返回值决定是否找到此数据项。 insert()方法向数组下一个空位置放置一个新的数据项。一个名为nElems的字段跟踪记录着...

沉迷于编程的小菜菜
今天
1
1
fiddler安装和基本使用以及代理设置

项目需求 由于开发过程中客户端和服务器数据交互非常频繁,有时候服务端需要知道客户端调用接口传了哪些参数过来,这个时候就需要一个工具可以监听这些接口请求参数,已经接口的响应的数据,这种...

银装素裹
今天
0
0
Python分析《我不是药神》豆瓣评论

读取 Mongo 中的短评数据,进行中文分词 对分词结果取 Top50 生成词云 生成词云效果 看来网上关于 我不是药神 vs 达拉斯 的争论很热啊。关于词频统计就这些,代码中也会完成一些其它的分析任...

猫咪编程
今天
0
0
虚拟机怎么安装vmware tools

https://blog.csdn.net/tjcwt2011/article/details/72638977

AndyZhouX
昨天
1
0
There is no session with id[xxx]

参考网页 https://blog.csdn.net/caimengyuan/article/details/52526765 报错 2018-07-19 23:04:35,330 [http-nio-1008-exec-8] DEBUG [org.apache.shiro.web.servlet.SimpleCookie] - Found......

karma123
昨天
0
0

没有更多内容

加载失败,请刷新页面

加载更多

下一页

返回顶部
顶部