I’m declaring a ThreadLocal object and setting a value like below.
Public Class Blah {
private ThreadLocal<Set<Integer>> numberThreaLocalObj= new ThreadLocal<>();
void setValue() {
Set<Integer> numberSet = new HashSet<>();
numberSet .add(1);
threaLocalObj.set(numberSet)
}
}
Is there anyway to reference this numberThreaLocalObj variable outside of this class within the same thread?
I’ve found some code the seems to clear ALL the threadlocals, but I just need to clear this particular Threadlocal variable based on a condition.
Unfortunately this is a inherited technical design.
EDIT – SOLUTION FOUND as outlined in my answer.
Advertisement
Answer
I can use the following code to identify the specific threadlocal object I’m interested in Code is used from a previous post, which was answered by @lyaffe https://stackoverflow.com/users/509566/lyaffe
My thread local object in another class
private ThreadLocal<Set<Integer>> numberSetTL = new NamedThreadLocal<>("MY_NAMED_TL_NAME");
I’ve slightly modified the code to remove a specific Name. The ThreadLocal being removed would have to be a Spring NamedThreadLocal object.
private void cleanThreadLocals() {
try {
// Get a reference to the thread locals table of the current thread
Thread thread = Thread.currentThread();
Field threadLocalsField = Thread.class.getDeclaredField("threadLocals");
threadLocalsField.setAccessible(true);
Object threadLocalTable = threadLocalsField.get(thread);
// Get a reference to the array holding the thread local variables inside the
// ThreadLocalMap of the current thread
Class threadLocalMapClass = Class.forName("java.lang.ThreadLocal$ThreadLocalMap");
Field tableField = threadLocalMapClass.getDeclaredField("table");
tableField.setAccessible(true);
Object table = tableField.get(threadLocalTable);
// The key to the ThreadLocalMap is a WeakReference object. The referent field of this object
// is a reference to the actual ThreadLocal variable
Field referentField = Reference.class.getDeclaredField("referent");
referentField.setAccessible(true);
for (int i=0; i < Array.getLength(table); i++) {
// Each entry in the table array of ThreadLocalMap is an Entry object
// representing the thread local reference and its value
Object entry = Array.get(table, i);
if (entry != null) {
// Get a reference to the thread local object and remove it from the table
ThreadLocal threadLocal = (ThreadLocal)referentField.get(entry);
if(threadLocal instanceof NamedThreadLocal) {
if("MY_NAMED_TL_NAME".equalsIgnoreCase(threadLocal.toString())) {
threadLocal.remove();
LOG.debug(tlName + " - ThreadLocal found and removed.");
}
}
}
}
} catch(Exception e) {
// We will tolerate an exception here and just log it
throw new IllegalStateException(e);
}
}