说明: ThreadLocal必须new一个对象自己使用,如果使用共享变量不能解决线程安全的问题, 它并不是为了解决线程安全而设计的,也解决不了,使用它只是为了在同一线程中传递变量
下面来看一下这个工具类:
public enum ContextUtil {
INSTANCE;
private final static ThreadLocal<Map<String,Object>> threadLocal = new ThreadLocal<>();
private final ReentrantReadWriteLock lock = new ReentrantReadWriteLock();
private final String OPERATOR="operator";
private final String OWNER="owner";
public void clear(){
Map<String, Object> store = loadStore();
store.clear();
}
public void setOperator(Long operator){
Map<String, Object> store = loadStore();
store.put(OPERATOR,operator);
}
public Long getOperator(){
Map<String, Object> store = loadStore();
return (Long)store.get(OPERATOR);
}
public void setOwer(String owner){
Map<String, Object> store = loadStore();
store.put(OWNER,owner);
}
public String getOwner(){
Map<String, Object> store = loadStore();
return (String) store.get(OWNER);
}
//读写锁二次验证
private Map<String,Object> loadStore(){
lock.readLock().lock();
Map<String, Object> store = threadLocal.get();
if(null == store){
// Must release read lock before acquiring write lock
lock.readLock().unlock();
lock.writeLock().lock();
// Recheck state because another thread might have
// acquired write lock and changed state before we did.
store = threadLocal.get();
if(null==store){
store = new HashMap<>();
threadLocal.set(store);
}
// Downgrade by acquiring read lock before releasing write lock
lock.readLock().lock();
// Unlock write, still hold read
lock.writeLock().unlock();
}
lock.readLock().unlock();
return store;
}
这个工具类的主要作用是当多个用户用户登陆时, 保存下来每个用户的 “account_id”, 这样, 当这些用户做其他操作时, 后台直接从其对应线程中,就能获取到其对应的account_id.
loadStrore:
进入loadStore -> 加读锁 -> 拿到threadLocal中对应的内容 -> 内容为空 -> 释放读锁
内容不空 -> 释放读锁 -> 加写锁 -> 得到threalocal对应内容 -> 二次检查 -> 此时threadlocal中还是空 -> new一个空的hashmap并设置进去 -> 此时threadlocal中为一个空的map对象
此时threadlocal不是空, 说明其他线程已经存入了 -> 拿到当前线程的读锁 -> 释放写锁
Recheck state because another thread might have
acquired write lock and changed state before we did.
重新检查状态, 因为另一个线程可能获得了写锁并且在我们直之前改变threadlocal的值了.
关于threadload详解请点击: 查看