首先说明ThreadLocal存放的值是线程内共享的,线程间互斥的,主要用于线程内共享一些数据,避免通过参数来传递,这样处理后,能够优雅的解决一些实际问题,比如Hibernate中的OpenSessionInView,就是使用ThreadLocal保存Session对象,还有我们经常用ThreadLocal存放Connection,代码如:
- /**
- * 数据库连接管理类
- * @author 爽
- *
- */
- public class ConnectionManager {
- /** 线程内共享Connection,ThreadLocal通常是全局的,支持泛型 */
- private static ThreadLocal<Connection> threadLocal = new ThreadLocal<Connection>();
- public static Connection getCurrConnection() {
- // 获取当前线程内共享的Connection
- Connection conn = threadLocal.get();
- try {
- // 判断连接是否可用
- if(conn == null || conn.isClosed()) {
- // 创建新的Connection赋值给conn(略)
- // 保存Connection
- threadLocal.set(conn);
- }
- } catch (SQLException e) {
- // 异常处理
- }
- return conn;
- }
- /**
- * 关闭当前数据库连接
- */
- public static void close() {
- // 获取当前线程内共享的Connection
- Connection conn = threadLocal.get();
- try {
- // 判断是否已经关闭
- if(conn != null && !conn.isClosed()) {
- // 关闭资源
- conn.close();
- // 移除Connection
- threadLocal.remove();
- conn = null;
- }
- } catch (SQLException e) {
- // 异常处理
- }
- }
- }
这样处理的好处:
- 统一管理Connection;
- 不需要显示传参Connection,代码更优雅;
- 降低耦合性。
ThreadLocal有四个方法,分别为:
initialValue
protected T initialValue()
get()
方法访问变量的时候。如果线程先于 get 方法调用 set(T)
方法,则不会在线程中再调用 initialValue 方法。
该实现只返回 null;如果程序员希望将线程局部变量初始化为 null 以外的某个值,则必须为 ThreadLocal创建子类,并重写此方法。通常,将使用匿名内部类。initialValue 的典型实现将调用一个适当的构造方法,并返回新构造的对象。
get
public T get()
set
public void set(T value)
initialValue()
方法来设置线程局部变量的值。
value
- 存储在此线程局部变量的当前线程副本中的值。remove
public void remove()
很多人对ThreadLocal存在一定的误解,说ThreadLocal中有一个全局的Map,set时执行map.put(Thread.currentThread(), value),get和remove时也同理,但SUN的大师们是否是如此实现的,我们只能去看源码了。
set方法:
- /**
- * Sets the current thread's copy of this thread-local variable
- * to the specified value. Most subclasses will have no need to
- * override this method, relying solely on the {@link #initialValue}
- * method to set the values of thread-locals.
- *
- * @param value the value to be stored in the current thread's copy of
- * this thread-local.
- */
- public void set(T value) {
- // 获取当前线程对象
- Thread t = Thread.currentThread();
- // 获取当前线程本地变量Map
- ThreadLocalMap map = getMap(t);
- // map不为空
- if (map != null)
- // 存值
- map.set(this, value);
- else
- // 创建一个当前线程本地变量Map
- createMap(t, value);
- }
- /**
- * Get the map associated with a ThreadLocal. Overridden in
- * InheritableThreadLocal.
- *
- * @param t the current thread
- * @return the map
- */
- ThreadLocalMap getMap(Thread t) {
- // 获取当前线程的本地变量Map
- return t.threadLocals;
- }
这里注意,ThreadLocal中是有一个Map,但这个Map不是我们平时使用的Map,而是ThreadLocalMap,ThreadLocalMap是ThreadLocal的一个内部类,不对外使用的。当使用ThreadLocal存值时,首先是获取到当前线程对象,然后获取到当前线程本地变量Map,最后将当前使用的ThreadLocal和传入的值放到Map中,也就是说ThreadLocalMap中存的值是[ThreadLocal对象, 存放的值],这样做的好处是,每个线程都对应一个本地变量的Map,所以一个线程可以存在多个线程本地变量。
get方法:
- /**
- * Returns the value in the current thread's copy of this
- * thread-local variable. If the variable has no value for the
- * current thread, it is first initialized to the value returned
- * by an invocation of the {@link #initialValue} method.
- *
- * @return the current thread's value of this thread-local
- */
- public T get() {
- Thread t = Thread.currentThread();
- ThreadLocalMap map = getMap(t);
- if (map != null) {
- ThreadLocalMap.Entry e = map.getEntry(this);
- if (e != null)
- return (T)e.value;
- }
- // 如果值为空,则返回初始值
- return setInitialValue();
- }
有了之前set方法的分析,get方法也同理,需要说明的是,如果没有进行过set操作,那从ThreadLocalMap中拿到的值就是null,这时get方法会返回初始值,也就是调用initialValue()方法,ThreadLocal中这个方法默认返回null。当我们有需要第一次get时就能得到一个值时,可以继承ThreadLocal,并且覆盖initialValue()方法。
(完)
本文来自:高爽|Coder,原文地址:http://blog.csdn.net/ghsau/article/details/15732053
相关推荐
java ThreadLocal多线程专属的变量源码java ThreadLocal多线程专属的变量源码java ThreadLocal多线程专属的变量源码java ThreadLocal多线程专属的变量源码java ThreadLocal多线程专属的变量源码java ThreadLocal多...
Java线程:新特征-条件变量 Java线程:新特征-原子量 Java线程:新特征-障碍器 Java线程:深入ThreadLocal 一、标准例子 二、不用ThreadLocal 三、自己实现个ThreadLocal 四、透过现象看本质 Java线程:大...
Java 线程本地变量 ThreadLocal 详解 ThreadLocal 是 Java 中的一个类,提供了线程安全的对象封装,用于解决多线程访问数据的冲突问题。ThreadLocal 的主要目的是为每个线程提供一个变量副本,从而隔离了多个线程...
`Atomic`类:Java并发包(`java.util.concurrent.atomic`)提供了如`AtomicInteger`、`AtomicLong`等原子类,它们提供了原子操作,如`incrementAndGet()`,在多线程环境下可以替代`synchronized`和`volatile`,实现...
ThreadLocal是Java编程语言中的一个类,用于在多线程环境下提供线程局部变量。它为每个线程创建了一个独立的变量副本,每个线程只能访问自己的副本,不会影响其他线程。这种机制有助于实现线程安全,尤其在需要线程...
- **使用Lock接口**:Java提供如`ReentrantLock`这样的锁对象,也可以实现线程安全的临界区。相比于`synchronized`,`Lock`提供了更细粒度的控制,如尝试获取锁、可中断锁等待等。 使用临界区的关键在于正确地...
Java线程编程中的ThreadLocal类是一个非常重要的工具,它在多线程环境下提供了一种线程局部变量的机制。ThreadLocal并非是简单的变量,而是一种能够确保每个线程都拥有独立副本的变量容器。理解ThreadLocal的工作...
本话题聚焦于“多线程线程变量赋值”,讨论如何在不通过参数传递的情况下,为线程变量直接赋值。 首先,我们需要理解线程变量(Thread Local Variables)的概念。线程变量,也称为线程局部变量,是一种特殊类型的...
10. **线程局部变量(ThreadLocal)**:为每个线程提供独立的变量副本,确保线程间的隔离,避免了共享状态带来的问题。 实战部分将通过具体的代码示例展示如何创建和管理线程,如何实现线程同步,以及如何利用...
Java中的`ThreadLocal`类是一个非常实用的工具,它提供了线程局部变量的功能。线程局部变量意味着每个线程都拥有自己独立的变量副本,互不干扰,这在多线程编程中尤其有用,可以避免数据共享带来的同步问题。下面...
ThreadLocal 是 Java 语言中的一种机制,用于提供线程内部的局部变量。在多线程环境下,ThreadLocal 变量可以保证各个线程的变量相对独立于其他线程内的变量。这种机制可以帮助开发者在多线程环境下编写更加简洁、可...
ThreadLocal是Java中的一种机制,可以将变量与线程关联起来,使得每个线程都可以拥有自己的变量副本。 ThreadLocal的出现是为了解决多线程编程中的线程安全问题。 从本质上说,ThreadLocal是一种存储机制,它可以在...
4. **清理ThreadLocal:** 使用`remove()`方法可以清除当前线程的ThreadLocal副本中的值。请注意,当线程结束时,ThreadLocal的引用通常会自动清除,但为了防止内存泄漏,最好在不再需要时显式调用`remove()`。 ``...
8. 线程局部变量(ThreadLocal):为每个线程创建独立的变量副本,避免了线程安全问题,但要注意,ThreadLocal变量会在线程结束时被垃圾回收,如果不及时清理可能导致内存泄漏。 测试线程安全通常包括模拟并发环境...
而`ThreadLocal`则提供了另一种思路:为每个使用该变量的线程分配独立的副本,这样一来,每个线程拥有自己的变量副本,互不影响,从而避免了线程安全问题。 #### 二、ThreadLocal的数据结构及实现原理 `...
10. **线程本地存储(ThreadLocal)**:为每个线程提供独立的变量副本,避免了线程间的共享数据冲突。 11. **并发集合**:如ConcurrentHashMap、CopyOnWriteArrayList等,这些集合类在并发环境下提供了高性能的读写...
Java中的ThreadLocal是一个非常重要的工具类,它在多线程编程中扮演着独特角色,用于为每个线程提供独立的变量副本。理解ThreadLocal的工作原理和使用方法对于编写高效、安全的多线程程序至关重要。 ### ...
- **线程的创建**:Java提供了两种创建线程的方式,一是通过实现`Runnable`接口,二是继承`Thread`类。每种方式都有其适用场景,需要根据实际需求选择。 - **生命周期**:线程有新建、就绪、运行、阻塞和终止五种...
- `ThreadLocal`类提供线程局部变量,避免共享数据带来的问题。 #### 七、高级主题 - **线程池**: - 使用`ExecutorService`接口来管理和复用一组工作线程。 - 减少创建和销毁线程的开销。 - **并发集合与工具类*...
10. **线程Local变量**:`ThreadLocal`类为每个线程提供独立的变量副本,有效避免了线程安全问题。 以上知识点覆盖了Java线程的基础概念、创建方式、状态管理、同步机制以及高级特性,是Java程序员必须掌握的重要...