2016-06-30 4 views
1

Я немного начинаю, когда речь заходит о приложениях JAVA, но участвовала в разработке довольно сложного приложения JAVA (8), которое требует многопоточности. У меня и у другого разработчика все время возникала проблема, из-за которой приложение некоторое время не работает.JAVA Многопоточность, утечка памяти, сборщик мусора

Сначала мы предоставили приложение 64 ГБ памяти, но через несколько часов у него закончилась память, сбой и перезагрузка. Только продолжать делать это снова и снова. Контекст; Приложение принимает сообщения из системы обмена сообщениями (ActiveMQ), а из метаданных сообщения необходимо создать файл XML, вызвав различные источники данных для значений. Там может быть буквально миллионы сообщений, которые необходимо обработать, поэтому мы разработали многопоточную систему, каждый поток связан с сообщением - и дал приложение 40 потоков.

Однако, поскольку он продолжает принимать сообщения, общее потребление памяти увеличивается со временем. Я чувствую, что сборщик мусора не используется нами правильно?

Так что в данный момент у нас есть одна родительская нить:

(new Thread(new ReportMessageConsumer(config, ""))).start();

Тогда в ReportMessageConsumer мы имеем X число установки нитей, так что это будет в нашей текущей установке 40. Так что все это под одной группой. Как только XML был построен и потоки сделаны с тем, как мы эффективно убиваем поток и принудительно собираем сборщик мусора, чтобы освободить эту память, чтобы мы могли затем создать новый чистый поток, чтобы получить другое сообщение?

+0

Поток умирает вскоре после того, как его 'Run() метод' либо возвращает или вызывает исключение. Если ваш код не содержал ссылки на объект «Thread» (и ваш пример явно не сохраняет его), тогда объект «Thread» и все объекты, на которые ссылается стека потока, должны немедленно стать elgible, чтобы быть исправленными ГК. –

+2

Не используйте потоки напрямую, если вы хотите их убить, а другой - для обработки «другого сообщения»: используйте исполнителей. –

+0

Какое точное OutOfMemoryError вы видите? Это куча, стек, gc накладные расходы, неспособность создавать собственные потоки? –

ответ

3

Я чувствую, что сборщик мусора не используется нами правильно?

Это не проблема. Лучшее, что вы можете сделать, это позволить GC делать свое дело без каких-либо помех. Не пытайтесь заставить GC работать. Это редко полезно, и часто плохо для производительности.

Настоящая проблема заключается в том, что у вас есть утечка памяти. Это может произойти, потому что вы получаете все больше и больше потоков ... или это может быть что-то другое.

Я бы рекомендовал следующее:

  1. Rewrite вам код так, что он использует ExecutorService управлять ограниченным пулом потоков и очередь задач, которые будут работать на этих потоках. Посмотрите на javadocs для простого примера.

    Не стоит ничего, что использование пула потоков улучшает производительность вашего приложения. Создание потока (т. Е. Thread.start()) довольно дорого в Java.

  2. Если это не излечит вашу утечку, используйте инструмент профилирования памяти, чтобы узнать, как/почему ваше приложение утечки памяти. Есть много StackOverflow Q & A о том, как это сделать.Например:

+0

Спасибо, что-то вроде: 'executorService = (ThreadPoolExecutor) Executors.newFixedThreadPool (maxThread); while (true) { if (executorService.getActiveCount()

+1

Пул потоков, как и ExecutorService, должен иметь фиксированное количество потоков, поддерживаемых очередью. Таким образом, если вы назначаете 10 потоков для пула потоков, у него никогда не будет больше потоков, но если все потоки заняты, 'processMessage' будет поставлен в очередь для возможного выполнения. Другими словами, вам не нужно беспокоиться о 'getActiveCount' или управлении потоками –

+0

Спасибо, это упрощает! Итак, если в этот момент мы все еще сталкивались с утечками памяти, это связано с тем, что что-то внутри исполнительной службы сохраняется в памяти еще? Я думаю, когда мы вызываем executeorService.shutdown() в конце каждого обработанного сообщения, он должен очистить все от него с помощью GC? –