'ऐसा करने का एक और अच्छा तरीका' की रेखाओं के साथ, मैंने एक रननेबल रैपर बनाया जो पूर्व-मौजूदा थ्रेड लोकल का एक स्नैपशॉट लेता है, घोंसला चलाने योग्य चलाता है, फिर किसी थ्रेड लोकल को साफ़ करता है (शून्य पर सेट करता है) शुरुआत में उपस्थित नहीं था।
यह 'स्नैपशॉट' कोड को उप-वर्गीकृत निष्पादक के पहले एक्सेक्यूट() और 'क्लीनअप' कोड में @danben द्वारा सुझाए गए अनुसार 'क्लीनअप' कोड में डालकर बेहतर किया जा सकता है।
किसी भी तरह से, सौंदर्य यह है कि आपको कठोर कोड नहीं है जो थ्रेड स्थानीय को रखने या त्यागने के लिए नहीं है।
अव्यवस्था से निपटने के लिए स्रोत सूची से अपवाद हैंडलिंग हटा दी गई थी।
public class ThreadLocalCleaningRunnable implements Runnable
{
private final Runnable runnable;
public ThreadLocalCleaningRunnable(Runnable runnable) {
this.runnable = nonNull(runnable);
}
public void run() {
// printThreadLocals();
Set> initialThreadLocalKeys = getThreadLocalKeys();
try {
runnable.run();
}
finally {
cleanThreadLocalsExcept(initialThreadLocalKeys);
// printThreadLocals();
}
}
public static void printThreadLocals() {
Thread thread = Thread.currentThread();
Field threadLocalsField = Thread.class.getDeclaredField("threadLocals");
threadLocalsField.setAccessible(true);
Class threadLocalMapKlazz = Class.forName("java.lang.ThreadLocal$ThreadLocalMap");
Field tableField = threadLocalMapKlazz.getDeclaredField("table");
tableField.setAccessible(true);
Object threadLocals = threadLocalsField.get(thread);
if (threadLocals != null) {
Object table = tableField.get(threadLocals);
if (table != null) {
int threadLocalCount = Array.getLength(table);
String threadName = thread.getName();
for (int i = 0; i > getThreadLocalKeys() {
Thread thread = Thread.currentThread();
Set> threadLocalKeys = new HashSet>();
Field threadLocalsField = Thread.class.getDeclaredField("threadLocals");
threadLocalsField.setAccessible(true);
Class threadLocalMapKlazz = Class.forName("java.lang.ThreadLocal$ThreadLocalMap");
Field tableField = threadLocalMapKlazz.getDeclaredField("table");
tableField.setAccessible(true);
Object threadLocals = threadLocalsField.get(thread);
if (threadLocals != null) {
Object table = tableField.get(threadLocals);
if (table != null) {
int threadLocalCount = Array.getLength(table);
for (int i = 0; i) entry).get();
if (o instanceof ThreadLocal) {
threadLocalKeys.add((ThreadLocal) o);
}
}
}
}
}
return threadLocalKeys;
}
public static void cleanThreadLocalsExcept(Set> keptThreadLocalKeys) {
Thread thread = Thread.currentThread();
Field threadLocalsField = Thread.class.getDeclaredField("threadLocals");
threadLocalsField.setAccessible(true);
Class threadLocalMapKlazz = Class.forName("java.lang.ThreadLocal$ThreadLocalMap");
Field tableField = threadLocalMapKlazz.getDeclaredField("table");
tableField.setAccessible(true);
Object threadLocals = threadLocalsField.get(thread);
if (threadLocals != null) {
Object table = tableField.get(threadLocals);
if (table != null) {
int threadLocalCount = Array.getLength(table);
for (int i = 0; i) entry).get();
if (o instanceof ThreadLocal) {
ThreadLocal tl = (ThreadLocal) o;
if (!keptThreadLocalKeys.contains(tl)) {
Field valueField = entry.getClass().getDeclaredField("value");
valueField.setAccessible(true);
valueField.set(entry, null);
}
}
}
}
}
}
}
}
सहमत हुए। लेकिन मैं मौजूदा कोड में एक बग को ठीक करना चाहता हूं, इसे फिर से आर्किटेक्ट नहीं करना चाहता हूं। –