Java ColdFusion 9-我的线程保留了内存-我如何才能阻止它?

Java ColdFusion 9-我的线程保留了内存-我如何才能阻止它?,java,multithreading,memory,coldfusion,garbage-collection,Java,Multithreading,Memory,Coldfusion,Garbage Collection,我有一个特殊的线程,当BYCF9应用程序启动时,我会启动它。它管理一个队列,并从队列中提取项目来处理它们。如果队列中没有要提取的项目,它将sleep()。该线程可以生存数周,处理和睡眠等 我遇到的问题是,我从队列中提取的项目在我处理完之后很长时间都保留在堆中(看起来像旧一代) JVM大约每小时进行一次完整的垃圾收集(我可以从jConsole中看出这一点),即使在运行时,我处理的项目仍然保留在堆中。我之所以能说出这一点,是因为我进行了jmap堆转储,并使用内存分析工具Eclipse插件对其进行分析

我有一个特殊的线程,当BYCF9应用程序启动时,我会启动它。它管理一个队列,并从队列中提取项目来处理它们。如果队列中没有要提取的项目,它将
sleep()
。该线程可以生存数周,处理和睡眠等

我遇到的问题是,我从队列中提取的项目在我处理完之后很长时间都保留在堆中(看起来像旧一代)

JVM大约每小时进行一次完整的垃圾收集(我可以从jConsole中看出这一点),即使在运行时,我处理的项目仍然保留在堆中。我之所以能说出这一点,是因为我进行了
jmap
堆转储,并使用内存分析工具Eclipse插件对其进行分析

这是我的代码,在
应用程序中执行。cfc

<!--- Kick off a new thread and run through the queue --->
<cfthread action="run" name="myThread">

    <cfloop condition="APPLICATION.threadProcessing eq true">

        <cfif APPLICATION.myQueue.hasNext()>

            <!--- Get next item --->
            <cfset tmpItem = APPLICATION.myQueue.next() />

            <!--- Ask item to process itself --->
            <cfset tmpItem.process() />

            <!--- PROBLEM: these 'tmpItem' objects are never cleaned up by the garbage collector! ---> 

            <!--- Then we sleep for an interval - this is to stop us hogging server resources --->
            <cfset sleep(2000) />


        <cfelse>

            <!--- Nothing in the queue, so sleep for a while... --->
            <cfset sleep(10000) />

        </cfif>

    </cfloop>   

</cfthread>

有人能告诉我我是否使用了不正确的范围或什么吗?有没有办法强制清理我的临时对象?我认为调用显式垃圾收集不会起作用,因为它无论如何都不会被清理

当我们从CF8移到CF9时,这似乎才成为一个问题

感谢所有的帮助-我真的希望保持这种线程方法,而不是将其作为计划任务或其他什么运行


谢谢,西亚兰

您可能需要研究锁定应用程序范围的使用。

我可以提供两条建议。一个很不确定,但另一个很可靠

有人告诉我,虽然我没有测试过,但通过将空字符串分配给变量名,可以提前将对象释放到垃圾收集。本质上,您是在减少对象上的指针计数。我只在CF6.1环境中见过这种情况,所以我真的不确定它是否适用,假设它确实有效

如果是我,我会调查的是一项预定的任务。它不会经常运行(我认为最短等待时间是1分钟,IIRC),但应该在任务终止时释放调用使用的所有内存。基本上,您只需删除外部循环和sleep(),并以普通调用的方式调用页面。我不完全确定您的队列是如何工作的,但由于它在应用程序范围内,只要您的任务在应用程序树中(或包含该应用程序文件),您就应该能够访问它


根据你的其他评论,听起来这不是一个共享的环境。运行计划任务还有其他障碍吗?

如果我试图弄清这一点,我想知道是什么阻止了这些对象成为gc的,我会使用它,并查看是什么阻止了这些对象成为gc的


内存gc问题的另一个原因是重写Object.finalize()的对象,尽管听起来它不适用于您的情况。这是因为它们必须在回收之前由finalizer线程处理,如果它们的创建速度比finalizer线程处理速度快,则可能会遇到mem问题

我的理解是线程使用堆栈,而不是堆,因此线程内部没有“垃圾收集”。它们被保留在堆中,因为它们仍然在堆栈上。如果我错了,有人纠正我吗

我们已经讨论过了-锁定是由对象本身处理的,hasNext()会处理它。我假设Aaron所说的锁定是为了确保队列一致性-我在添加和从队列中获取时有相同的命名锁。嘿Ben-我尝试将对象设置为空字符串-没有乐趣。我们拥有这些盒子,我们一直在运行预定的任务,有时在neo-cron.XML文件上使用一些XML黑客技术,时间不到Adobe 1分钟。现在我添加了一个var关键字,也就是说,每100个项目中也添加了一个明确的垃圾回收调用,所以如果这不能修复它,那么安排的任务可能是下一个要考虑的事情。谢谢你的反馈。就像我说的,我真的不知道空字符串技巧是否真的有效。在我看来,这似乎有点可疑,但我工作的公司的首席技术人员说,它使用的是CF6。显式GC很好。显式GC不好,作为计划任务重写,这样就解决了内存问题。谢谢所有的反馈。我提到我正在使用jmap。创建堆的hprof格式转储。内存分析工具Eclipse类似于jhat,它显示CF线程持有所有对象。所以我知道泄漏的确切位置!我认为我的对象没有覆盖finalize()(至少我没有!),所以我不确定这是否适用。为什么不允许任务队列在项目用完后过期,并在创建新项目时重新初始化它?@Daniel-线程才是真正的问题,因此,我可以以某种方式重新启动线程,因为这是保存在对象(内存)上的内容。这与使用计划任务的想法几乎相同。任务启动,然后在队列上的所有可用对象中运行,直到完成为止。然后停止并在稍后检查队列。如果每次添加任务时都检查线程是否存在,则甚至不必使用调度程序。如果它存在,那么你附加到它,如果它不存在,那么你产生它。。。不需要安排时间。这是一直都在发生,还是只在负载下发生?@Aaron-这种情况总是发生,负载不是一个因素。我曾考虑过生成一个线程,但在这种情况下,调度任务更简单。谢谢你的建议。