我有一个实现Runnable
的类,目前正在使用Executor作为我的线程池来运行任务(将文档索引到Lucene中)。
executor.execute(new LuceneDocIndexer(doc, writer));
我的问题是我的Runnable类创建了许多Lucene Field
对象,我宁愿重复使用它们,然后在每次调用时创建新对象。重用这些对象的最佳方法是什么(Field
对象不是线程安全的,所以我不能简单地将它们设置为静态) - 我应该创建自己的ThreadFactory
吗?我注意到一段时间后程序开始急剧下降,我唯一能想到的就是它的GC开销。我目前正试图描述该项目,以确保这甚至是一个问题 - 但现在让我们假设它是。
答案 0 :(得分:14)
您的问题询问如何重复使用Runnable,因此我将忽略其他详细信息并简单回答该问题。
如果您使用的是ThreadPoolExecutor,则可以使用[ThreadPoolExecutor #afterExecute] [1]方法将Runnable对象返回到'cached'Runnables的池/队列。
[1]:http://java.sun.com/javase/6/docs/api/java/util/concurrent/ThreadPoolExecutor.html#afterExecute(java.lang.Runnable,java.lang.Throwable)
答案 1 :(得分:5)
Runnable对象是可重用的。它不是线程对象。
最好的方式?这是你的方式: - )
我认为这比一个可运行的问题更像是一个简单的问题。
答案 2 :(得分:1)
您可能希望进行更多基准测试,以确定导致减速的原因。
我愿意打赌你的问题与Field实例的创建无关。 Field没有任何终结器,并且它们不是为了合并而设计的。
答案 3 :(得分:1)
现在我决定只使用一个简单的Producer-> Consumer模型。我将BlockingQueue
传递给每个索引器,而不是将文档传递给索引,然后让程序的主驱动程序将新文档添加到该队列。索引器然后反馈[有界]队列并重用Field
个对象并共享线程安全的IndexWriter
。
我找到了一个我可能没有打电话给HttpMethod.releaseConnection()
的地方,这可能导致我的记忆问题(不确定)。