java中清理/删除未使用的地图元素的策略
我正在我的网络应用程序中实现一个“管理器”,可以调用它来设置和获取当前线程所在的网站上下文(我们对我们的网站进行白色标记,以便网站上下文代表我们所在的网站)
我'我正在尝试找出执行此操作的最佳策略,目前我正在并发哈希映射中实现将线程存储到 WebSiteContext:
private final ConcurrentHashMap<Thread, WebSiteContext> chm = new ConcurrentHashMap<Thread, WebSiteContext>();
在线程的开头(通过 Servlet Filter 或通过手动设置它)线程将关联到其 WebSiteContext,
但希望清理 Map 以避免内存泄漏。所以我想一种策略是迭代映射的 Thread 键以查明线程是否“活动”(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);
}
}
}
}
但是我想这需要我同步对地图的访问(或者确实如此?)这是我想避免的。
是否有任何“惯用”模式用于在 java 中的线程中存储属性或确实清理以 Thread 对象作为键的映射?我愿意使用 WeakReference / SoftReferences 或者实际上如果有 Thread.getCurrentThread().setAttribute(Object, Object) 的等效项,那就太好了
干杯 西蒙·B
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
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(4)
你有没有想过
ThreadLocal
?Have you thought about
ThreadLocal
?你的方法可能有效,但你最终会做比需要的更多的工作。 ThreadLocal 是您正在寻找的。这将允许您存储与应用程序中每个线程相关的对象。使用它的典型方法是实现initialValue() 方法,该方法为其分配第一个值。示例:
当您第一次调用 localAttribute.get() 时,这将为您提供一个新的本地线程,其初始值为“InitialValue”。然后您可以调用 localAttribute.set() 为其分配不同的值。每个请求者线程对于同一属性将具有不同的值。
使用 ThreadLocal 的好处是,当线程终止时,线程本地应该允许您的数据可用于垃圾回收。
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:
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.
您正在为一个 Servlet 调用的持续时间定义一个“线程本地”变量空间。这里最好的方法是在添加映射的同一级别删除映射,因此,如果您在
ServletFilter
中添加映射,我会添加一个finally
块,该块已删除出路时的地图。这同样适用于 Servlet 中的“手动”添加。替代方案是在您的
ServletContext
中包含此信息,或者将其添加为ThreadLocal
属性。You are defining a "thread local" variable space for the duration of one servlet call. The best way here is to remove the mapping at the same level as you added it, so if you add to the map in a
ServletFilter
I would add afinally
block that removed the mapping on the way out. The same holds for a "manual" addition in a servlet.Alternatives are having this information in your
ServletContext
or adding it as aThreadLocal
attribute.