private static final ThreadLocal<UserInfo> userInfoThreadLocal = new ThreadLocal<>() ;
时间: 2024-05-24 11:08:48 浏览: 296
private static final ThreadLocal<UserInfo> userInfoThreadLocal = new ThreadLocal<>() 是一个Java语言中的ThreadLocal变量声明,它用于在多线程环境中存储每个线程独有的UserInfo对象。ThreadLocal是Java语言中的一个线程级别的变量,每个线程都有自己独立的ThreadLocal变量,不同的线程之间互不干扰。这个变量声明为private static final表示这个变量是一个私有、静态、不可变的常量,它只能在类内部被访问和修改。
通过使用ThreadLocal,我们可以在多线程环境下避免线程安全问题。例如,在Web应用程序中,每个请求都有一个独立的线程,我们可以使用ThreadLocal来存储当前请求的用户信息,这样就可以避免不同请求之间的用户信息相互干扰。当然,在使用ThreadLocal时也需要注意内存泄漏的问题,要及时清理不再需要使用的ThreadLocal对象。
相关问题
threadLocal 发送短信
### 使用 `ThreadLocal` 实现线程安全的短信发送
在Java中,`ThreadLocal` 提供了一种方法来创建仅限于单个线程的变量副本。这意味着每个线程都有自己独立的一份数据拷贝,从而避免了多线程环境下的并发访问问题。
对于实现线程安全的短信发送功能而言,可以通过如下方式使用 `ThreadLocal`:
#### 定义 ThreadLocal 变量存储用户信息
首先定义一个静态的 `ThreadLocal<UserInfo>` 来保存当前正在处理的用户的特定信息。这确保了即使在同一时间有多个请求到来,不同线程之间也不会互相干扰。
```java
public class UserInfoHolder {
private static final ThreadLocal<String> userInfo = new ThreadLocal<>();
public static void setUserInfo(String info){
userInfo.set(info);
}
public static String getUserInfo(){
return userInfo.get();
}
public static void clear(){
userInfo.remove(); // 清除资源防止内存泄漏
}
}
```
#### 创建异步任务类用于实际执行短信发送操作
该类实现了 `Runnable` 接口,并在其内部调用了第三方API完成具体的短消息投递工作。注意这里并没有直接传递任何参数给构造函数;相反地,它依赖于前面提到过的 `ThreadLocal` 存储器获取必要的上下文信息。
```java
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
class SmsSenderTask implements Runnable {
@Override
public void run() {
try{
System.out.println("Sending SMS to user: " + UserInfoHolder.getUserInfo());
// Simulate sending an SMS message using some external service...
Thread.sleep(2000);
System.out.println("SMS sent successfully.");
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
throw new RuntimeException(e.getMessage(),e);
} finally {
UserInfoHolder.clear(); // Clean up after ourselves.
}
}
}
```
#### 主程序入口处启动异步任务
当接收到一个新的注册请求时,在主线程内先将所需的信息存入 `ThreadLocal` ,之后再提交至线程池等待被执行。这种方式既保证了效率又不会影响用户体验。
```java
ExecutorService executor = Executors.newFixedThreadPool(10);
// Assume this method is called when a registration request comes in.
void handleRegistrationRequest(UserInfo newUser) {
UserInfoHolder.setUserInfo(newUser.toString());
// Submit the task asynchronously so that we don't block here waiting for it to complete.
executor.submit(new SmsSenderTask());
}
// Remember to shut down your ExecutorService at application exit or during cleanup phase.
executor.shutdown();
```
通过上述设计模式,可以有效地提高应用程序的安全性和响应速度,同时也简化了代码结构[^2]。
ThreadLocal用在拦截器保存用户信息
### 使用 ThreadLocal 在 Spring 拦截器中保存和传递用户信息
#### 1. 定义 ThreadLocal 存储用户信息
为了在线程内安全地存储用户信息,定义一个静态 `ThreadLocal` 变量来持有这些信息。这确保了每个线程都有自己独立的副本。
```java
public class UserContextHolder {
private static final ThreadLocal<UserInfo> userContext = new ThreadLocal<>();
public static void setUser(UserInfo userInfo) {
userContext.set(userInfo);
}
public static UserInfo getUser() {
return userContext.get();
}
public static void clearUser() {
userContext.remove();
}
}
```
此代码片段展示了如何通过 `ThreadLocal` 来封装用户的上下文信息[^3]。
#### 2. 创建自定义拦截器
接下来,在 Spring MVC 中配置一个拦截器,以便可以在请求处理的不同阶段捕获并设置用户信息到 `ThreadLocal` 中。
```java
import org.springframework.stereotype.Component;
import org.springframework.web.servlet.HandlerInterceptor;
@Component
public class UserContextInterceptor implements HandlerInterceptor {
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
String userId = extractUserIdFromRequest(request); // 假设这里是从请求头或其他地方获取用户ID的方法
if (userId != null && !userId.isEmpty()) {
UserInfo userInfo = new UserInfo(userId);
UserContextHolder.setUser(userInfo);
}
return true;
}
@Override
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
UserContextHolder.clearUser(); // 请求结束后清理ThreadLocal中的数据
}
private String extractUserIdFromRequest(HttpServletRequest request) {
// 这里可以根据实际情况调整逻辑,比如从JWT令牌、Cookie或HTTP头部提取用户ID
return request.getHeader("X-User-ID");
}
}
```
这段代码实现了在每次 HTTP 请求到达之前读取用户 ID 并将其存入 `ThreadLocal` 的功能;当请求完成之后,则清除掉这个临时存储的数据以防止内存泄漏[^1]。
#### 3. 注册拦截器
为了让上述拦截器生效,还需要把它注册到应用程序的全局过滤链路当中去:
```java
@Configuration
public class WebConfig implements WebMvcConfigurer {
@Autowired
private UserContextInterceptor userContextInterceptor;
@Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(userContextInterceptor).addPathPatterns("/**"); // 应用于所有路径下的API调用
}
}
```
以上就是完整的流程说明以及具体实现方式,利用 `ThreadLocal` 和 Spring 提供的拦截机制能够有效地在整个请求生命周期内保持住必要的用户身份验证信息而不必每次都手动传递它们[^2]。
阅读全文
相关推荐













