【问题标题】:Would holding a reference to a Thread object cause memory leak? [duplicate]持有对 Thread 对象的引用会导致内存泄漏吗? [复制]
【发布时间】:2015-03-30 09:21:38
【问题描述】:

我想编写一个代理来确保特定对象只在特定线程上使用,因此我需要持有对 Thread 对象的引用(正如 JavaDoc 所说的 id 可以重用)。这个引用会导致线程(不是 Thread 对象)在终止时没有被完全垃圾回收吗?

【问题讨论】:

  • 这将导致Thread 不会被垃圾收集,并且所有对象都可以从它访问。 thread 是一个操作系统实体,根本不受垃圾收集的影响。你的问题没有意义。
  • 我想我已经尽可能清楚了:有我自己的实例想要持有的Thread 类的实例(即Thread 对象),并且有JVM线程(如调度概念)。前者暴露了操作后者的方法,但目前尚不清楚持有对前者的引用是否会阻止后者被完全垃圾回收(考虑到 ThreadLocals 和有关线程泄漏的经验)。
  • 不仅你的问题听起来很奇怪,而且整个设计也很奇怪。为什么您认为应该只允许一个特定线程更新(读取、写入?)特定对象?我的意思是:那个对象的生命周期和那个“操作”线程不同吗?
  • @EddyG 我承认这是一个不寻常的模式。我使用的外部库有一个对象池,但是在代码库中的某处对象被过早地返回到池中,导致在多个线程上使用了一个非线程安全的对象。我想写一个代理来检测这种情况。当对象从池中取出时,代理应该存储对currentThread的引用,如果调用线程与存储的Thread不同,则抛出。
  • 我会说这是一个 JVM 特定的主题,其答案在 Java 标准中没有指定(查看 JVM 内部)

标签: java garbage-collection


【解决方案1】:

我想编写一个代理来确保特定对象只在特定线程上使用,所以我需要持有对 Thread 对象的引用

你没有。您可以使用仅在特定线程中设置的ThreadLocal<Boolean>

这个引用会导致线程(不是线程对象)在终止时没有被完全垃圾回收吗?

您的引用会导致Thread 泄漏,但正如@superbob 所写,操作系统线程会发生什么尚未明确。只要您知道它实际上只是一个线程,我就不会在意。

虽然ThreadLocal 也可能是leak,但没有子类化(尤其是不使用initialValue())的简单ThreadLocal<Boolean> 不会泄漏任何东西。


我使用的外部库有一个对象池,但在代码库中的某处对象被过早地返回到池中,导致在多个线程上使用了一个非线程安全的对象。我想写一个代理来检测这种情况。当对象从池中取出时,代理应该存储对 currentThread 的引用,如果调用线程与存储的线程不同,则抛出。

这听起来与您的问题完全不同,似乎使我的上述答案无效。我很久以前写过这样的东西:

import com.google.common.collect.MapMaker;

public static synchronized boolean singleThreaded(Object o) {
    final Thread neu = Thread.currentThread();
    final Thread old = threadMap.put(o, neu);
    return old==null || old==neu;
}

private final static Map<Object, Thread> threadMap =
    new MapMaker().weakKeys().weakValues().makeMap();

并在调试时使用它以确保 someObject 在单个线程中通过

assert singleThreaded(someObject)

由于所有引用都很弱,我希望没有泄漏

【讨论】:

  • 是的,我最后也走上了弱参考之路。
猜你喜欢
  • 2017-06-28
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-08-13
  • 1970-01-01
  • 1970-01-01
  • 2017-09-11
相关资源
最近更新 更多