2010-05-05 2 views
4

У меня есть класс, который реализует Runnable и в настоящее время я использую Executor в качестве пула потоков для запуска задач (индексирование документов в Lucene).Лучший способ повторного использования Runnable

executor.execute(new LuceneDocIndexer(doc, writer)); 

Моя проблема заключается в том, что мой Runnable класс создает много Lucene Field объектов, и я предпочел бы повторно использовать их тогда создавать новые каждый вызов. Каков наилучший способ повторного использования этих объектов (объекты Field не являются потокобезопасными, поэтому я не могу сделать их статичными) - должен ли я создать свой собственный ThreadFactory? Я замечаю, что через некоторое время программа начинает резко ухудшаться, и единственное, о чем я могу думать, это накладные расходы на GC. В настоящее время я пытаюсь профилировать проект, чтобы убедиться, что это даже проблема, но пока давайте просто предположим, что это так.

+0

У меня нет предыдущего опыта в Lucene; но можно ли использовать пул объектов «Поле»? –

+0

Каждый объект «Поле» отличается (например, 6 на каждый документ), поэтому использование одного пула общих объектов не будет работать. Я также не хочу отслеживать 6 пулов объектов, которые должны быть того же размера, что и мой пул потоков, поэтому, если я когда-либо изменю размер пула потоков, я должен изменить размер пула объектов - не звучит очень ремонтопригодны. – Gandalf

+0

GC должен быть оптимизирован для работы с небольшими выделениями, которые быстро исчезают, поскольку это такой распространенный вариант использования. Я не знаком с Lucene, но если объекты Field достаточно малы и достаточно короткими, вероятность того, что они выделены в стеке JIT и даже не достигнут GC. – Skrud

ответ

1

На данный момент я решил использовать просто модель Продюсер-> Потребитель. Я передаю BlockingQueue каждому индексу, а не документу для индексации, а затем, чтобы основной драйвер программы добавлял новые документы в эту очередь. Индексаторы затем подают эту [ограниченную] очередь и повторно используют объекты Field и обмениваются потокобезопасными IndexWriter.

Я нашел место, где я, возможно, не звонил HttpMethod.releaseConnection(), так что это могло вызвать проблемы с памятью (неопределенный).

5

Объект Runnable является многоразовым. Это объект потока, которого нет.

Лучший способ? это ваш путь :-)

Я думаю, что это более люцинный вопрос, чем вопрос, который можно решить.

+0

Я думаю, что у вас есть это в обратном направлении. – Gandalf

+1

@ Gandalf: Этот плакат абсолютно прав. Это ваша проблема, что ваша реализация «Runnable» не является потокобезопасной. Если бы это было так, вы могли бы определенно передать его дважды (или более) исполнителю. –

1

Возможно, вы захотите провести еще один бенчмаркинг, чтобы пригвоздить то, что вызывает замедление.

Я готов поспорить, что ваша проблема не связана с созданием экземпляров Field. В поле нет финализаторов, и они не предназначены для объединения.

12

Ваш вопрос задает вопрос о повторном использовании Runnable, поэтому я буду игнорировать другие детали и просто ответить на этот вопрос.

Если вы используете ThreadPoolExecutor, вы можете использовать метод [ThreadPoolExecutor # afterExecute] [1], чтобы вернуть объект Runnable в пул/очередь «кэшированных» Runnables.

[1]: http://java.sun.com/javase/6/docs/api/java/util/concurrent/ThreadPoolExecutor.html#afterExecute(java.lang.Runnable, java.lang.Throwable)

+0

Удивительно, что вы единственный, кто ответил на этот вопрос и не стал говорить об обстоятельствах. +1! – user289463

Смежные вопросы