一 概述ThreadLocal是什么?ThreadLocal并非是一个线程的本地实现版本,它并不是一个Thread,而是线程局部变量—threadlocalvariable。也许把它命名为ThreadLocalVar更加合适。ThreadLocal其实的功用非常简单,就是为每一个使用该变量的线程都提供一个变量值的副本,是Java中一种较为特殊的线程绑定机制,是每一个线程都可以独立地改变自己的副本,而不会和其它线程的副本冲突。从线程的角度看,每个线程都保持一个对其线程局部变量副本的隐式引用,只要线程是活动的并且ThreadLocal实例是可访问的;在线程消失之后,其线程局部实例的所有副本都会被垃圾回收(除非存在对这些副本的其他引用)。通过ThreadLocal存取的数据,总是与当前线程相关,JVM为每个运行的线程,绑定了私有的本地实例存取空间,从而为多线程环境常出现的并发访问问题提供了一种隔离机制。ThreadLocal是如何做到为每一个线程维护变量的副本的呢?思路很简单,在ThreadLocal类中有一个Map,用于存储每一个线程的变量的副本。对于多线程资源共享的问题,同步机制采用了以时间换空间的方式,仅提供一份变量,让不同的线程排队访问。
ThreadLocal采用了以空间换时间的方式,每一个线程都提供了一份变量,因此可以同时访问而互不影响。二 API说明
ThreadLocal()创建一个线程本地变量。T get()返回此线程局部变量的当前线程副本中的值,如果这是线程第一次调用该方法,则创建并初始化此副本。protected T initialValue()返回此线程局部变量的当前线程的初始值。最多在每次访问线程来获得每个线程局部变量时调用此方法一次,即线程第一次使用get()方法访问变量的时候。如果线程先于get方法调用set(T)方法,则不会在线程中再调用initialValue方法。若该实现只返回null;如果程序员希望将线程局部变量初始化为null以外的某个值,则必须为ThreadLocal创建子类,并重写此方法。通常,将使用匿名内部类。initialValue的典型实现将调用一个适当的构造方法,并返回新构造的对象。void remove()移除此线程局部变量的值。这可能有助于减少线程局部变量的存储需求。如果再次访问此线程局部变量,那么在默认情况下它将拥有其 initialValue。void set(T value)将此线程局部变量的当前线程副本中的值设置为指定值。许多应用程序不需要这项功能,它们只依赖于initialValue()方法来设置线程局部变量的值。在程序中一般都重写initialValue方法,以给定一个特定的初始值。public class ThreadLocal{ private Map values = Collections.synchronizedMap(new HashMap()); public Object get() { Thread curThread = Thread.currentThread(); Object o = values.get(curThread); if (o == null && !values.containsKey(curThread)) { o = initialValue(); values.put(curThread, o); } return o; } public void set(Object newValue) { values.put(Thread.currentThread(), newValue); } public Object initialValue() { return null; }}三 典型实例Hiberante的Session工具类HibernateUtil。这个类是Hibernate官方文档中HibernateUtil类,用于session管理。public class HibernateUtil{ private static Log log = LogFactory.getLog(HibernateUtil.class); private static final SessionFactory sessionFactory; static { try { // 通过默认配置文件hibernate.cfg.xml创建SessionFactory sessionFactory = new Configuration().configure().buildSessionFactory(); } catch (Throwable ex) { log.error("初始化SessionFactory失败!", ex); throw new ExceptionInInitializerError(ex); } } // 创建线程局部变量session用来保存Hibernate的Session public static final ThreadLocal session = new ThreadLocal(); // 获取当前线程中的Session public static Session currentSession() throws HibernateException { Session s = (Session) session.get(); if (s == null) { // 将新开的Session保存到线程局部变量中 s = sessionFactory.openSession(); session.set(s); } return s; } public static void closeSession() throws HibernateException { Session s = (Session) session.get(); session.set(null); if (s != null) s.close(); }}对代码进行分析1 public static final ThreadLocal session = new ThreadLocal();2 public static Session currentSession() {3 Session s = (Session)session.get();4 if(s == null){5 s = sessionFactory.openSession();6 session.set(s);7 }8 return s;9 }总体分析该类由于没有重写ThreadLocal的initialValue()方法,则首次创建线程局部变量session其初始值为null。第一次调用currentSession()的时候,线程局部变量的get()方法也为null。因此对session做了判断如果为null,则新开一个Session,并保存到线程局部变量session中,这一步非常的关键。逐行分析第一行初始化。如果不初始化initialvalue则initialvalue为null。第三行session的get根据当前线程返回其对应的线程内部变量,也就是我们需要的net.sf.hibernate.Session相当于对应每个数据库连接。多线程情况下共享数据库链接是不安全的。ThreadLocal保证了每个线程都有自己的s数据库连接。第四行如果是该线程初次访问,自然s会是null,接着创建一个Session,具体就是第五行。第五行创建一个数据库连接实例s。第六行保存该数据库连接s到ThreadLocal中。第七行如果当前线程已经访问过数据库了,则从session中get()就可以获取该线程上次获取过的连接实例。四 总结ThreadLocal使用场合主要解决多线程中数据因并发产生不一致问题。ThreadLocal为每个线程的中并发访问的数据提供一个副本。
原帖地址:http://lavasoft.blog.51cto.com/62575/51926/
分享到:
相关推荐
threadlocal源码解析
ThreadLocal类的作用:为每个线程创建独立的副本,从而保证了线程安全。 ThreadLocal使用代码示例: public class MyThreadLocalTest { private ThreadLocal threadLocal=new ThreadLocal(){ @Override protected...
解析源码内容,包括threadlocalmap中怎么解决hash冲突,以及set时得各种场景,还有set时什么条件会触发扩容机制,并且说明在过期桶中为什么要清除这些数据信息。
今天小编就为大家分享一篇关于Java源码解析ThreadLocal及使用场景,小编觉得内容挺不错的,现在分享给大家,具有很好的参考价值,需要的朋友一起跟随小编来看看吧
导致JVM内存泄露的ThreadLocal详解 为什么要有ThreadLocal ThreadLocal的使用 实现解析 引发的内存泄漏分析 错误使用ThreadLocal导致 线程不安全分析
Java并发编程学习宝典(漫画版),Java并发编程学习宝典(漫画版)Java并发编程学习宝典(漫画版)Java并发编程学习宝典(漫画版)Java并发编程学习宝典(漫画版)Java并发编程学习宝典(漫画版)Java并发编程学习...
ThreadLocal为解决多线程程序的并发问题提供了一种新的思路,ThreadLocal并不是一个Thread,而是Thread的局部变量,本文就来深入解析Java中ThreadLocal线程类的作用和用法.
ThreadPoolExecutor源码解析.pdf
ThreadLocal 使用及实现原理.mp4 并发工具类CountDownLatch详解.mp4 并发工具类CyclicBarrier 详解.mp4 并发工具类Semaphore详解.mp4 并发工具类Exchanger详解.mp4 CountDownLatch,CyclicBarrier,Semaphore源码解析....
基于SpringBoot的轻量级redis事务回滚机制,使用栈和ThreadLocal记录业务链的redis操作,发生异常进行回滚,参考了阿里巴巴Seata AT模式的db回滚策略:补偿回滚,记录前镜像与当前操作语句,反向解析生成补偿动作。...
TransactionEventHandler 检查布尔 ThreadLocal 变量。 根据这一点,检查 TransactionData 是否有任何写入。 如果找到,则抛出异常以否决提交此事务。 当 Neo4j 作为服务器运行时,缺少另一部分。 我们不知何故...
no7_threadlocal ThreadLocal实例及源码解析 no8_volatile volatile实例 no9_daemon_thread 守护线程实例 no10_threadgroup 线程组 no11_thread_catch_exception 指定异常捕获类捕获线程中的异常 no12_...
InheritableThreadLocal跟ThreadLocal差不多,关键点在Thread#init方法中会对Thread中的实例变量inheritableThreadLocals进行赋值操作,将父线程的本地变量复制到子线程中 首先通过ServiceLoader.load方法生成一个...
1.什么是多线程 2.Thread类解析 3.使用多线程需要注意的问题 4.synchronized锁和lock锁 5.AQS 6.ReentrantLock和ReentrantReadWriteLock 7.线程池 8.死锁 9.线程常用的工具栏 10.Atomic 11.ThreadLocal
由阿里的电商业务规则、表达式(布尔组合)、特殊数学公式计算(高精度)、语法分析、脚本二次定制等强需求而设计的一门动态脚本引擎解析工具。 在阿里集团有很强的影响力,同时为了自身不断优化、发扬开源贡献精神...
主要介绍了Java多线程编程中需要注意的一些关键点,包括ThreadLocal变量与原子更新等一些深层次的内容,需要的朋友可以参考下
使用ThreadLocal自定义查询缓存 Instrument 基于Java Instrument的Agent实现 Annotation 关于Java注解的使用Annotation Spring 关于Spring底层理解 HappyParse 各种Java解析小工具 PlayCenter 业务算法小工具(抢红包...
第36节ThreadLocal 使用及实现原理00:17:41分钟 | 第37节并发工具类CountDownLatch详解00:22:04分钟 | 第38节并发工具类CyclicBarrier 详解00:11:52分钟 | 第39节并发工具类Semaphore详解00:17:27分钟 | 第40节...
第36节ThreadLocal 使用及实现原理00:17:41分钟 | 第37节并发工具类CountDownLatch详解00:22:04分钟 | 第38节并发工具类CyclicBarrier 详解00:11:52分钟 | 第39节并发工具类Semaphore详解00:17:27分钟 | 第40节...