(线程上线文)
一、自定义类使用ThreadLocal
可以创建多个ThreadLocal变量
ThreadLocal<HashMap>存储多个变量,感觉用起来不是很方便。使用需要测试。
感觉没必要用ConcurrentHasMap,因为ThreadLocal本身就是线程变量。应该不会有线程冲突。
import java.util.HashMap;
public class ThreadContextHolder {
//一个变量
private static final ThreadLocal<String> redisId = new ThreadLocal<>();
//另一个变量
private static final ThreadLocal<String> remoteAddr = new ThreadLocal<>();
//Map放多个变量
protected static final ThreadLocal<HashMap> authMap = new ThreadLocal<HashMap>();
public static String getRedisId() {
return ThreadContextHolder.redisId.get();
}
public static void setRedisId(String redisId) {
ThreadContextHolder.redisId.set(redisId);
}
public static String getRemoteAddr() {
return ThreadContextHolder.remoteAddr.get();
}
public static void setRemoteAddr(String remoteAddr) {
ThreadContextHolder.remoteAddr.set(remoteAddr);
}
public static HashMap getAuthMap() {
return ThreadContextHolder.authMap.get();
}
public static void setAuthMap(HashMap authMap) {
ThreadContextHolder.authMap.set(authMap);
}
public static void main(String[] args) throws Exception {
try{
ThreadContextHolder.redisId.set("redisId1");
ThreadContextHolder.remoteAddr.set("remoteAddr1");
//其他类调用
System.out.println(ThreadContextHolder.getRedisId());
System.out.println(ThreadContextHolder.getRemoteAddr());
} catch (Exception ex) {
ex.printStackTrace();
} finally {
//清理,避免内存泄露
ThreadContextHolder.remoteAddr.remove();
ThreadContextHolder.redisId.remove();
}
try{
HashMap map1 = new HashMap();
map1.put("a1", "a1");
map1.put("a2", "a2");
authMap.set(map1);
//其他类调用
HashMap map2 = ThreadContextHolder.getAuthMap();
System.out.println(map2.get("a1"));
System.out.println(map2.get("a2"));
} catch (Exception ex) {
ex.printStackTrace();
} finally {
ThreadContextHolder.authMap.remove();
}
//线程调试
new Thread(() -> {
//...
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}, "thread-1").start();
}
}
二、JDK内部ThreadContext类
com.sun.jmx.snmp.ThreadContext,在JDK 9中移除,不推荐使用。
可以自己复制一份。感觉也没那么好用,主要是清理这块,有点特殊。
java 线程上下文是内部专有API,将来可能会删除 _大数据知识库
//ThreadContext oldContext = ThreadContext.push(stringKey, objectValue);
ThreadContext oldContext = null;
try {
oldContext = ThreadContext.push("stringKey1","objectValue1");
ThreadContext.push("stringKey2","objectValue2");
} finally {
if (oldContext != null) {
ThreadContext.restore(oldContext);
}
}
//其他类调用
String value1 = ThreadContext.get("stringKey1");
Object value2 = ThreadContext.get("stringKey2");
三、log4j(和shiro)的ThreadContext类
log4j和shiro 带ThreadContext类,但是感觉用他们的(依赖他们的)不好,使用倒是方便
log4j
org.apache.logging.log4j.ThreadContext
try {
...
ThreadContext.put("stringKey1", "stringvalue1");
ThreadContext.put("stringKey2", "stringvalue2");
}
catch (Exception e){
e.printStackTrace();
}
finally {
//清除ThreadContext,避免内存泄露
ThreadContext.clearAll();
}
//其他类调用
String value1 = ThreadContext.get("stringKey1");
String value2 = ThreadContext.get("stringKey2");