ThreadLocal如何实现多线程资源共享
来源:互联网 发布:黑客学python还是php 编辑:程序博客网 时间:2024/05/07 10:02
一、概念
ThreadLocal是什么呢?API中这样描述:该类提供了线程局部 (thread-local) 变量。这些变量不同于它们的普通对应物,因为访问某个变量(通过其 get 或 set 方法)的每个线程都有自己的局部变量,它独立于变量的初始化副本。ThreadLocal 实例通常是类中的 private static 字段,它们希望将状态与某一个线程(例如,用户 ID 或事务 ID)相关联。
其实ThreadLocal并非是一个线程的本地实现版本,它并不是一个Thread,而是threadlocalvariable(线程局部变量)。也许把它命名为ThreadLocalVar更加合适。线程局部变量(ThreadLocal)其实的功用非常简单,就是为每一个使用该变量的线程都提供一个变量值的副本,是Java中一种较为特殊的线程绑定机制,是每一个线程都可以独立地改变自己的副本,而不会和其它线程的副本冲突。
从线程的角度看,每个线程都保持一个对其线程局部变量副本的隐式引用,只要线程是活动的并且 ThreadLocal 实例是可访问的;在线程消失之后,其线程局部实例的所有副本都会被垃圾回收(除非存在对这些副本的其他引用)。
二、原理
创建了几个线程在map中就有对应的key,value值如下图:
在ThreadLocal1线程下调用方法传递的线程变量为key1,再调用方法method2的时候还是传递key1,所以在整个线程中共享变量。
三、项目中应用
在drp项目许多方法要共享Connection变量,所以用到ThreadLocal,代码如下:
public class ConnectionManager {private static ThreadLocal<Connection> connectionHolder = new ThreadLocal<Connection>();/** * 得到connection */public static Connection getConnection(){Connection conn = connectionHolder.get();//如果当前线程中没有绑定相应的connectionif(conn == null){ try {jdbcConfig jdbcConfig = XmlConfigReader.getInstance().getjdbcConfig();Class.forName(jdbcConfig.getDriverName());conn = DriverManager.getConnection(jdbcConfig.getUrl(),jdbcConfig.getUserName(),jdbcConfig.getPassword());//将connection设置到线程ThreadLocal中connectionHolder.set(conn); }catch(ClassNotFoundException e) { e.printStackTrace(); throw new ApplicationException("系统错误,请联系系统管理员!"); } catch (SQLException e) {e.printStackTrace(); throw new ApplicationException("系统错误,请联系系统管理员!");} }return conn;}
这样把Connection放到ThreadLocal中,在线程级别下,方法调用可以共享Connection。
四、误区
1、ThreadLocal是java线程的一个实现
ThreadLocal的确是和java线程有关,不过它并不是java线程的一个实现,它只是用来维护本地变量。针对每个线程,提供自己的变量版本,主要是为了避免线程冲突,每个线程维护自己的版本。彼此独立,修改不会影响到对方。
2、ThreadLocal是相对于每个session的
ThreadLocal顾名思义,是针对线程。在java web编程上,每个用户从开始到会话结束,都有自己的一个session标识。但是ThreadLocal并不是在会话层上。其实,Threadlocal是独立于用户session的。它是一种服务器端行为,当服务器每生成一个新的线程时,就会维护自己的ThreadLocal。对于这个误解,个人认为应该是开发人员在本地基于一些应用服务器测试的结果。众所周知,一般的应用服务器都会维护一套线程池,也就是说,对于每次访问,并不一定就新生成一个线程。而是自己有一个线程缓存池。对于访问,先从缓存池里面找到已有的线程,如果已经用光,才去新生成新的线程。所以,由于开发人员自己在测试时,一般只有他自己在测,这样服务器的负担很小,这样导致每次访问可能是共用同样一个线程,导致会有这样的误解:每个session有一个ThreadLocal
3ThreadLocal是相对于每个线程的,用户每次访问会有新的ThreadLocal
理论上来说,ThreadLocal是的确是相对于每个线程,每个线程会有自己的ThreadLocal。但是上面已经讲到,一般的应用服务器都会维护一套线程池。因此,不同用户访问,可能会接受到同样的线程。因此,在做基于TheadLocal时,需要谨慎,避免出现ThreadLocal变量的缓存,导致其他线程访问到本线程变量
五、总结
ThreadLocal使用场合主要解决多线程中数据数据因并发产生不一致问题。ThreadLocal为每个线程的中并发访问的数据提供一个副本,通过访问副本来运行业务,这样的结果是耗费了内存,单大大减少了线程同步所带来性能消耗,也减少了线程并发控制的复杂度。
ThreadLocal和Synchonized都用于解决多线程并发访问。但是ThreadLocal与synchronized有本质的区别。synchronized是利用锁的机制,使变量或代码块在某一时该只能被一个线程访问。而ThreadLocal为每一个线程都提供了变量的副本,使得每个线程在某一时间访问到的并不是同一个对象,这样就隔离了多个线程对数据的数据共享。而Synchronized却正好相反,它用于在多个线程间通信时能够获得数据共享。
Synchronized用于线程间的数据共享,而ThreadLocal则用于线程间的数据隔离。
- ThreadLocal如何实现多线程资源共享
- Java多线程如何实现资源共享
- 【java】实现多线程资源共享
- 多线程实现资源共享
- ThreadLocal实现多线程
- ThreadLocal资源共享问题
- 多线程实现资源共享 ——购票操作
- 多线程资源共享
- 多线程资源共享
- ThreadLocal,实现安全的多线程
- 【Java多线程】ThreadLocal实现原理
- 如何实现局域网内两台电脑资源共享?
- 实现Runnable,轻松实现多线程间的资源共享
- java多线程------实现Runnable接口创建多进程,实现资源共享
- 如果用Runnable就可以实现资源共享[Java多线程]
- 多线程实现资源共享的问题学习与总结
- 多线程实现资源共享的问题学习与总结
- 多线程资源共享的问题
- Android TextView自动换行文字排版参差不齐的原因
- MAC OS X下配置 Django + MongoDB
- android 拼音快速检索ListView
- 走进Visual C++
- mysql 启停
- ThreadLocal如何实现多线程资源共享
- 使用Gnu gprof进行Linux平台下的程序分析
- 阿里巴巴集团2014秋季校园招聘系统工程师北京站笔试题 答案
- VMware Workstation虚拟机网络连接杂记、给Windows虚拟机配置固定IP
- java的学习指导
- 设计数据需要注意事项
- android基础笔记:Activity启动模式
- 关于解决:the constructor AlertDialog.Builder(new View.OnClickListener() ) is undefined
- 适配器模式--(java io中用到了装饰着模式,适配器模式)