0

我在我的网络应用程序中实现了一个“管理器”,可以调用它来设置和获取当前线程所在的网站上下文(我们给我们的网站贴上白标签,所以网站上下文代表我们在哪个网站上)

我正在尝试找出执行此操作的最佳策略,目前我正在并发哈希映射中将线程存储到 WebSiteContexts:

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

在线程开始时(通过 Servlet 过滤器或通过手动设置),线程将关联到它的 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 对象作为键的映射?我愿意使用 Wea​​kReference / SoftReferences,或者如果有一些等价的 Thread.getCurrentThread().setAttribute(Object, Object),那就太好了

干杯西蒙B

4

4 回答 4

2

你有没有想过ThreadLocal

于 2009-11-02T12:56:57.977 回答
1

您的方法可能会奏效,但您最终会做的工作超出需要。ThreadLocal是您正在寻找的。这将允许您在应用程序中存储与每个线程相关的对象。使用它的典型方法是实现为它分配第一个值的 initialValue() 方法。例子:

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

当您第一次调用 localAttribute.get() 时,这将为您提供一个初始值为“InitialValue”的新本地线程。然后,您可以调用 localAttribute.set() 为其分配不同的值。每个请求者线程将具有相同属性的不同值。

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

于 2009-11-02T13:04:52.110 回答
0
于 2009-11-02T12:57:48.433 回答
0

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

替代方案是在您的信息中包含此信息ServletContext或将其添加为ThreadLocal属性。

于 2009-11-02T13:04:36.540 回答