Нерест тонны потоков без памяти - PullRequest
3 голосов
/ 20 декабря 2011

У меня есть многопоточное приложение, которое создает сотни потоков на лету. Когда JVM имеет меньше доступной памяти, чем необходимо для создания следующего Thread, он не может создать больше потоков. Каждая нить живет по 1-3 минуты. Есть ли способ, если я создаю поток и не запускаю его, можно заставить приложение автоматически запускать его, когда у него есть ресурсы, и в противном случае ждать, пока существующие потоки не умрут?

Ответы [ 4 ]

2 голосов
/ 20 декабря 2011

Недавно я столкнулся с подобной проблемой и использовал решение NotifyingBlockingThreadPoolExecutor, описанное на этом сайте:

http://today.java.net/pub/a/today/2008/10/23/creating-a-notifying-blocking-thread-pool-executor.html

Основная идея заключается в том, что этот NotifyingBlockingThreadPoolExecutor будет выполнять задачи параллельно, как ThreadPoolExecutor, но если вы попытаетесь добавить задачу, и нет доступных потоков, она будет ждать. Это позволило мне сохранить код с простым подходом «создай все задачи, которые мне нужны, как только они мне понадобятся», избегая при этом огромных накладных расходов на ожидающие задачи, создаваемые сразу.

Непонятно из вашего вопроса, но если вы используете прямые потоки вместо Executors и Runnables, вы должны изучить пакет java.util.concurrent и использовать его вместо этого: http://docs.oracle.com/javase/tutorial/essential/concurrency/executors.html

2 голосов
/ 20 декабря 2011

Вы несете ответственность за проверку доступной памяти перед выделением большего количества ресурсов, если вы работаете близко к своему пределу. Один из способов сделать это - использовать класс MemoryUsage или один из:

Runtime.getRuntime().totalMemory()
Runtime.getRuntime().freeMemory()

... чтобы увидеть, сколько памяти доступно. Чтобы выяснить, сколько используется , конечно, вы просто вычтите total из free. Затем в вашем приложении просто установите значение MAX_MEMORY_USAGE, которое, когда ваше приложение использовало этот объем или больше памяти, прекращает создавать больше потоков, пока количество используемой памяти не будет опустился ниже этого порога. Таким образом, вы всегда работаете с максимальным количеством потоков и не превышаете доступную память.

Наконец, вместо того, чтобы пытаться создавать потоки без их запуска (поскольку, создав объект Thread, вы уже занимаете память), просто выполните одно из следующих действий:

  • Сохраняйте очередь вещей, которые необходимо сделать, и создавайте новую ветку для этих вещей, когда память становится доступной
  • Используйте «пул потоков», скажем, максимум 128 потоков, как все ваши «рабочие». Когда рабочий поток завершает работу с заданием, он просто проверяет очередь ожидающих заданий, чтобы узнать, ожидает ли что-либо выполнения, и, если это так, удаляет это задание из очереди и начинает работу.
1 голос
/ 20 декабря 2011

Просто напишите код, чтобы делать именно то, что вы хотите. Ваш вопрос описывает рецепт решения, просто реализуйте этот рецепт. Кроме того, вы должны серьезно подумать о ре-архитектуре. Вам нужен поток только для того, что вы хотите сделать одновременно , и вы не можете с пользой делать сотни вещей одновременно.

0 голосов
/ 20 декабря 2011

Это альтернативное решение более низкого уровня. Затем вышеупомянутый исполнитель NotifyingBlocking - он, вероятно, не так идеален, но будет прост в реализации

Если вы хотите, чтобы в режиме ожидания было много потоковтогда вам в конечном итоге понадобится механизм, чтобы они знали, когда можно «ожить».Это звучит как случай для семафоров.

Убедитесь, что каждый поток не выделяет ненужной памяти, прежде чем он начнет работать.Затем выполните следующие действия:

1) создайте n потоков при запуске приложения, сохраненных в очереди.Вы можете основывать это n на результате Runtime.getMemory (...), вместо того, чтобы жестко его кодировать.

2), также создав семафор с разрешениями nk.Опять же, основывайте это на количестве доступной памяти.

3) теперь пусть каждый из nk-потоков периодически проверяет, есть ли у семафора разрешения, вызывая, например, Thread.sleep (...) между проверками.

4) если поток замечает разрешение, обновите семафор и получите разрешение.

Если это удовлетворяет вашим потребностям, вы можете продолжить управление потоками с помощью более сложного опроса илимеханизм ожидания / блокировки позже.

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