内存泄漏—java中清理/删除未使用的Map元素的策略

a7qyws3x  于 2021-07-05  发布在  Java
关注(0)|答案(4)|浏览(441)

我在我的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

kmpatx3s

kmpatx3s1#

java.lang.threadlocal;
将目标信息绑定到servlet请求属性;

nr9pn0ug

nr9pn0ug2#

你有没有想过 ThreadLocal ?

6bc51xsx

6bc51xsx3#

你的方法可能有用,但你最终会做更多的工作。threadlocal是您需要的。这将允许您存储与应用程序中每个线程相关的对象。使用它的典型方法是实现initialvalue()方法,该方法将第一个值赋给它。例子:

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

当您第一次调用localattribute.get()时,这将为您提供一个初始值为“initialvalue”的新线程local。然后可以调用localattribute.set()为其赋值。对于同一属性,每个请求者线程将有不同的值。
使用threadlocal的好处是,当线程死亡时,threadlocal应该允许您的数据可用于垃圾收集。

evrscar2

evrscar24#

您正在为一个servlet调用的持续时间定义一个“线程局部”变量空间。这里最好的方法是在添加Map的同一级别上删除Map,因此如果在 ServletFilter 我会加一个 finally 在出去的路上移除了Map的块。servlet中的“手动”添加也是如此。
另一种选择是把这些信息放在你的电脑里 ServletContext 或将其添加为 ThreadLocal 属性。

相关问题