0

我在我的web应用程序中实现了一个“管理器”,可以调用它来设置和获取当前线程所在的网站上下文(我们在我们的网站上标记了白色网站方面表示我们是哪个网站上)在java中的策略来清理/删除未使用的地图元素

我试图找出什么是最好的策略,做到这一点,我目前正在执行的线程的商店在并发哈希地图WebSiteContexts:

private final ConcurrentHashMap<Thread, WebSiteContext> chm = new ConcurrentHashMap<Thread, WebSiteContext>(); 

在线程的开始处(通过Servlet过滤器或通过手动设置它)该线程将关联到其WebSiteContext,

但希望清理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); 
       } 
      } 
     } 
    } 

,但我猜这需要我同步对地图的访问(或者是否?),这是我想避免的。

是否有任何“惯用”模式存储java中的线程属性或确实清理了具有Thread对象作为键的映射?我打开使用的WeakReference/SoftReferences或者事实上如果有Thread.getCurrentThread()的一些等价的。的setAttribute(对象,对象),这将是巨大

干杯 西蒙乙

回答

1

你的方法可能会工作,但你最终会做的工作比neeeded多。 ThreadLocal是你在找什么。这将允许您在应用程序中存储与每个线程相关的对象。使用它的典型方法是实现initialValue()方法,该方法为其分配第一个值。例如:

private static final ThreadLocal<String> localAttribute = new ThreadLocal<String>() { 
     protected Integer initialValue() { 
      return "InitialValue"; 
    } 
}; 

这会给你一个新的线程局部与初始值“与InitialValue”当你第一次调用localAttribute.get()。然后可以调用localAttribute.set()为其分配一个不同的值。每个请求者线程对于相同的属性将具有不同的值。

使用ThreadLocal的好处是,当线程死亡时,本地线程应允许您的数据可用于垃圾收集。

+0

干杯,这正是我需要的东西,已经纳入它,它似乎工作正常,像你说,好的是在线程不再活着之后GC会清理干净 – 2009-11-03 16:55:52

2

你有没有想过ThreadLocal

+0

+1我不认为有什么更好的选择 – sfussenegger 2009-11-02 12:59:57

+0

这似乎正是我所需要的,欢呼 – 2009-11-02 13:18:51

0

您正在为一个servlet调用的持续时间定义一个“线程本地”变量空间。这里最好的办法是删除与添加它相同级别的映射,所以如果你添加到ServletFilter的地图中,我会添加一个finally块,以便在出路时删除映射。这同样适用于servlet中的“手动”添加。

替代品在您的ServletContext中收录此信息或将其作为ThreadLocal属性添加。