publicclassThreadLocal<T>{staticclassThreadLocalMap{staticclassEntryextendsWeakReference<ThreadLocal<?>>{/** The value associated with this ThreadLocal. */Objectvalue;Entry(ThreadLocal<?>k,Objectv){super(k);value=v;}}}}
/**
* Get the entry associated with key. This method
* itself handles only the fast path: a direct hit of existing
* key. It otherwise relays to getEntryAfterMiss. This is
* designed to maximize performance for direct hits, in part
* by making this method readily inlinable.
*
* @param key the thread local object
* @return the entry associated with key, or null if no such
*/privateEntryThreadLocalMap.getEntry(ThreadLocal<?>key){inti=key.threadLocalHashCode&(table.length-1);Entrye=table[i];if(e!=null&&e.get()==key)returne;elsereturngetEntryAfterMiss(key,i,e);}/**
* Version of getEntry method for use when key is not found in
* its direct hash slot.
*
* @param key the thread local object
* @param i the table index for key's hash code
* @param e the entry at table[i]
* @return the entry associated with key, or null if no such
*/privateEntryThreadLocalMap.getEntryAfterMiss(ThreadLocal<?>key,inti,Entrye){Entry[]tab=table;intlen=tab.length;while(e!=null){ThreadLocal<?>k=e.get();if(k==key)returne;if(k==null)expungeStaleEntry(i);elsei=nextIndex(i,len);e=tab[i];}returnnull;}
publicclassThreadLocalUtil{privatestaticfinalLoggerlogger=LoggerFactory.getLogger(ThreadLocalUtil.class);privatestaticThreadLocal<ThreadContext>threadLocal=newThreadLocal<>();publicstaticvoidput(Stringkey,Objectvalue){logger.debug("===== put key: [{}] value: [{}] in threadLocal =====",key,SerializeUtil.toJsonString(value));ThreadContextthreadContext=threadLocal.get();if(Objects.isNull(threadContext)){threadContext=newThreadContext();threadLocal.set(threadContext);}threadContext.put(key,value);}publicstaticObjectget(Stringkey){logger.debug("===== get value of key: [{}] from threadLocal =====",key);ThreadContextcontext=threadLocal.get();if(Objects.isNull(context)){returnnull;}returncontext.get(key);}publicstatic<T>Tget(Stringkey,Class<T>clazz){logger.debug("===== get value of key: [{}] class: [{}] from threadLocal =====",key,clazz.getName());ThreadContextcontext=threadLocal.get();if(Objects.isNull(context)){returnnull;}returncontext.get(key,clazz);}publicstaticvoidclear(){logger.debug("====== clear threadLocal =====");threadLocal.remove();}publicstaticvoidsetThreadLocal(ThreadContextthreadLocal){}publicstaticThreadLocal<ThreadContext>getThreadLocal(){returnthreadLocal;}}publicclassThreadContext{privateMap<String,Object>contextMap;publicThreadContext(){this.contextMap=newHashMap<>();}public<T>Tget(Stringkey,Class<T>clazz){returnclazz.cast(contextMap.get(key));}publicObjectget(Stringkey){returncontextMap.get(key);}publicvoidput(Stringkey,Objectvalue){contextMap.put(key,value);}publicMap<String,Object>getContextMap(){returncontextMap;}publicvoidsetContextMap(Map<String,Object>contextMap){this.contextMap=contextMap;}}