ThreadLocal最常用的场景:一个对象并非是线程安全的,但是你想让每个线程中访问的该对象是唯一的,不会和其他线程冲突,那么你就要用到ThreadLocal了。
举个简单的例子,比如SimpleDateFormat对象,不是线程安全的,假设该对象在多线程访问下会出问题,发生冲突,那么应该让每个线程只获取到唯一的该对象的实例,而且彼此线程不能访问对方的该实例。
package com.example;
import java.text.SimpleDateFormat;
import java.util.Date;
public class DateFormat {
private static final ThreadLocal<SimpleDateFormat> dateFormat =
new ThreadLocal<SimpleDateFormat>() {
protected SimpleDateFormat initialValue() {
return new SimpleDateFormat("yyyy-MM-dd");
};
};
public String format(Date date){
return dateFormat.get().format(date);
}
public static void main(String[] args){
DateFormat df=new DateFormat();
System.out.println(df.format(new Date()));
}
}
用这个简单的例子去看struts2中的ActionContext,就会理解它的用意了。tomcat对每一个request开启一个线程,然后运行Action代理,这就要求每个Action的环境变量parameters,locale等不会被其他线程访问而造成冲突。
仔细看ThreadLocal的源代码,可以发现ThreadLocal本身并不用来存储变量,只有三个静态变量:
private final int threadLocalHashCode = nextHashCode();
private static AtomicInteger nextHashCode =
new AtomicInteger();
private static final int HASH_INCREMENT = 0x61c88647;
真正的变量存储在当前Thread里面:
/* ThreadLocal values pertaining to this thread. This map is maintained
* by the ThreadLocal class. */
ThreadLocal.ThreadLocalMap threadLocals = null;
ThreadLocal用作ThreadLocal.ThreadLocalMap的key,而ThreadLocal threadLocalHashCode 的作用无非就是更快的查找到ThreadLocalMap对应的Entry罢了。
举个简单的例子,就是不同的类有自己的静态ThreadLocal(初始时生成唯一threadLocalHashCode标识),通过ThreadLocal存储value时(如上个例子的SimpleDateFormat实例),实际上以ThreadLocal为key,然后和value组成entry存储在当前线程的ThreadLocal.ThreadLocalMap threadLocals中。各自的类在调用value时,会首先在当前线程中以ThreadLocal为key进行查找(没有找到则调用initialValue()创建)。
线程类Thread负责线程的运行和线程变量的存储,而ThreadLocal则是负责变量的管理,各司其职。
分享到:
相关推荐
- `HttpClient学习笔记.doc`: 可能包含了关于Apache HttpClient的使用教程,包括如何创建HTTP请求,执行GET和POST操作,以及设置请求头和处理响应等内容。 - `HTTP中Get与Post的区别.doc`: 深入解析HTTP协议中的GET...
来源:码匠笔记前言 在我们日常 Web 开发中难免遇到需要把一个参数层层的传递到最内层,然后中间层根本不需要使用这个参数,或者是仅仅在特定的工具类中使用,这样我们完全没有必要在每一个方法里面都传递这样一个 ...
笔记会解释线程的创建、同步和通信,包括synchronized关键字、wait/notify机制、ThreadLocal等。 7. **反射与注解**:反射允许在运行时检查类、接口、字段和方法的信息,而注解为代码提供元数据。这两部分都是Java...
一个新构建的线程对象是由其父线程来进行空间分配的,而子线程继承了父线程的是否为 Daemon、优先级和加载资源的 contextClassLoader 以及可继承的 ThreadLocal,同时会分配一个唯一的 ID 来标识这个线程。...
下面,我们将根据这个主题,探讨一些关键的Java并发编程知识点。 1. **线程与进程**:在多任务环境中,线程是执行的基本单元,而进程是资源分配的最小单位。Java中的线程可以通过继承`Thread`类或实现`Runnable`...
15. **使用ThreadLocal确保线程封闭性:** 通过`ThreadLocal`可以在每个线程中存储独立的副本,从而避免线程间的数据竞争。 16. **单一不可变对象的优势:** 不可变对象在多线程环境中是线程安全的,应尽可能使用不...
但过度使用可能导致内存泄漏,因为线程结束时,ThreadLocal的值不会自动清除,除非手动调用remove()。 4. **ReentrantReadWriteLock**: 读写锁允许多个读线程同时访问资源,但在写操作时会独占资源。这种锁提高了...
- 线程安全:synchronized、volatile关键字的使用,以及ThreadLocal的概念。 - 并发工具类:如Semaphore、CyclicBarrier、CountDownLatch等,用于协同多线程执行。 - Executor框架:ThreadPoolExecutor的配置和...
`ThreadLocal`类及应用技巧 - **功能**:提供线程局部变量,每个线程拥有独立的变量副本,避免了线程间的共享数据冲突。 - **应用**:适用于需要在线程间隔离数据的场景,例如数据库连接、用户会话等。 ##### 5. ...
本学习笔记将深入探讨JUC的基础知识,帮助你理解和掌握Java并发编程的核心概念。 在Java中,多线程是实现并发的主要方式。一个线程是程序执行的一个流,多线程则意味着一个程序内可以同时执行多个线程。Java提供了...
- **多线程**:线程的创建与同步,包括synchronized、wait/notify、ThreadLocal等机制。 - **网络编程**:Socket编程,理解TCP/IP协议栈,实现简单的客户端和服务端程序。 - **Java 8及以上新特性**:Lambda...
### Hibernate 3.2 学习笔记:一对一主键关联详解 #### 一、一对一主键关联概述 在本节中,我们将详细探讨 Hibernate 3.2 中的一对一关联关系,尤其是通过主键实现的双向关联。这种关联通常出现在需要紧密绑定两个...
本笔记将深入探讨无锁编程的概念、原理以及在Java中的实现方式。 首先,理解无锁编程的核心思想是关键。无锁编程,也称为Lock-Free Programming,是指在多线程环境下,通过避免使用传统的锁机制(如synchronized或...
这包括线程的创建、同步机制(如synchronized关键字、wait()、notify()和notifyAll()方法)、线程安全的容器、ThreadLocal和死锁问题。 5. **异常处理**:异常处理是Java程序健壮性的关键。学习如何使用try-catch-...
在“JavaWeb笔记集合1”中,我们可以看到一些关键知识点,包括数据库管理、前端处理和后端交互。 首先,MySQL是一种广泛使用的开源关系型数据库管理系统,它支持SQL(结构化查询语言),用于数据的存取和管理。SQL...
Java高手笔记-工程师必须知道的事 本文档总结了Java开发中的一些常见问题和解决方案,涵盖了多线程、数据库事务、数据库索引、判等问题、数值计算、集合类、文件上传、日志、spring框架等方面。 并发工具 在Web...
同时,Java的并发库(如synchronized、volatile、ThreadLocal等)可以帮助开发者编写安全的并发程序。 9. **反射机制**:Java的反射机制允许在运行时动态地获取类的信息,并能直接操作类的对象,是实现动态代理、...
16. 使用ThreadLocal变量可以确保线程封闭性,例如hibernate openSessionInView机制和jdbc的connection机制。 17. 单一不可变对象往往是线程安全的,但是复杂不可变对象需要保证其内部成员变量也是不可变的。 18. ...
11. ThreadLocal:ThreadLocal为每个线程提供了一个独立的变量副本,各个线程修改自己的副本不会影响其他线程,常用于解决线程安全问题,例如在Servlet容器中,每个请求对应一个线程,ThreadLocal可以用于存储请求...