我在我的web应用程序中实现了一个“管理器”,可以调用它来设置和获取当前线程所在的网站上下文(我们为网站添加了白色标签,以便网站上下文表示我们所在的网站)
我正在尝试找出实现这一点的最佳策略,目前我正在并行哈希Map中实现将线程存储到WebSiteContext:
private final ConcurrentHashMap<Thread, WebSiteContext> chm = new ConcurrentHashMap<Thread, WebSiteContext>();
在线程开始时(通过servlet过滤器或手动设置),线程将与其websitecontext相关联,
但是要清理Map以避免内存泄漏。因此,我猜一种策略是迭代Map的线程键,以确定线程是否“活动”(thread.isalive()),如果不是,则删除它,例如:
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);
}
}
}
}
,但我想这需要我同步访问Map(或者是吗?),这是我想要避免的。
在java中,有没有“惯用”的模式来存储线程中的属性,或者清理以线程对象为键的Map?我对使用weakreference/softreferences持开放态度,如果真的有thread.getcurrentthread().setattribute(object,object)的等价物,那就太好了
干杯simon b
4条答案
按热度按时间kmpatx3s1#
java.lang.threadlocal;
将目标信息绑定到servlet请求属性;
nr9pn0ug2#
你有没有想过
ThreadLocal
?6bc51xsx3#
你的方法可能有用,但你最终会做更多的工作。threadlocal是您需要的。这将允许您存储与应用程序中每个线程相关的对象。使用它的典型方法是实现initialvalue()方法,该方法将第一个值赋给它。例子:
当您第一次调用localattribute.get()时,这将为您提供一个初始值为“initialvalue”的新线程local。然后可以调用localattribute.set()为其赋值。对于同一属性,每个请求者线程将有不同的值。
使用threadlocal的好处是,当线程死亡时,threadlocal应该允许您的数据可用于垃圾收集。
evrscar24#
您正在为一个servlet调用的持续时间定义一个“线程局部”变量空间。这里最好的方法是在添加Map的同一级别上删除Map,因此如果在
ServletFilter
我会加一个finally
在出去的路上移除了Map的块。servlet中的“手动”添加也是如此。另一种选择是把这些信息放在你的电脑里
ServletContext
或将其添加为ThreadLocal
属性。