I'm implementing a "manager" in my web app that can be called to set and get which web site context the current thread is in (we white label our site so the web site context represents which site we're on)
I'm trying to work out what the best strategy to do this, currently I'm implementing the store of Threads to WebSiteContexts in a concurrent hash map:
private final ConcurrentHashMap<Thread, WebSiteContext> chm = new ConcurrentHashMap<Thread, WebSiteContext>();
at the beginning of the thread (either through a Servlet Filter or through manually setting it) the thread will be associated to its WebSiteContext,
but want to clean up the Map to avoid a memory leak. So I guess one strategy is to iterate through the Thread keys of the map to find out whether the threads are "alive" (thread.isAlive()) and if not remove it for example like this:
public class Cleaner implements Runnable {
private static final int INTERVAL = 6 * 1000; // 6 seconds
public Cleaner() {
}
public void run() {
// soo every interval iterate through the threads if they're dead then remove it from the map.
while(true) {
try {
Set<Thread> threads = chm.keySet();
Set<Thread> staleThreads = new HashSet<Thread>();
for (Thread tmpThread : threads) {
// if we get to a dead thread then clean the fucker up
if (!tmpThread.isAlive()) {
// think that we're going to get a run condition anyway
chm.remove(tmpThread);
}
}
Thread.sleep(INTERVAL);
} catch (Exception e) {
log.error("caught exception e:", e);
}
}
}
}
, but this I guess requires me to synchronize access to the map (or does it?) which is something I want to avoid.
Is there any "idiomatic" pattern for storing attributes in threads in java or indeed cleaning up maps that have Thread objects as keys? I'm open to using WeakReference / SoftReferences or indeed if there is some equivalent of Thread.getCurrentThread().setAttribute(Object, Object), that would be great
Cheers Simon B
Your approach may work but you would end up doing more work than neeeded. ThreadLocal is what you are looking for. This will allow you to store objects related to each thread in your application. The typical way to use it is to implement the initialValue() method which assigns it the first value. Example:
private static final ThreadLocal<String> localAttribute = new ThreadLocal<String> () {
protected Integer initialValue() {
return "InitialValue";
}
};
This will give you a new thread local with the initial value to "InitialValue" when you first call localAttribute.get(). You can then call localAttribute.set() to assign it a different value. Each requester thread will have different values for the same attribute.
The nice thing about using ThreadLocal is that when the thread dies, the thread local should allow your data to be available for garbage collection.