Является ли один поток Java лучше, чем несколько потоков в моем сценарии? - PullRequest
2 голосов
/ 18 августа 2010

Наша компания запускает приложение Java (на сервере Windows с одним процессором) для чтения данных из сокета TCP / IP и проверки конкретных критериев (с помощью регулярных выражений), а если совпадение найдено, то сохраните данные в База данных MySQL. Данные огромны и считываются со скоростью 800 записей в секунду, и около 70% записей будут совпадать с записями, поэтому требуется много операций записи в базу данных. Программа использует LinkedBlockingQueue для обработки данных. Класс производителя просто читает запись и помещает ее в очередь, а класс потребителя удаляет из очереди и выполняет обработку.

Так что вопрос: поможет ли мне, если я использую несколько потребительских потоков вместо одного? Действительно ли многопоточность полезна в приведенном выше сценарии (поскольку я использую один процессор)? Я ищу предложения о том, как ускорить (без изменения оборудования).

Любые предложения будут очень признательны. Спасибо

Ответы [ 6 ]

2 голосов
/ 18 августа 2010

Простой: попробуйте и посмотрите.

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

Но первый вопрос, который вам нужно задать себе:

Что лучше?
Как вы оцениваете лучше?

Ответь на два вопроса и попробуй.

1 голос
/ 18 августа 2010

Прежде всего:
Желательно создавать приложение, используя java 5 одновременный API

Если ваше приложение создано вокруг ExecutorService , то довольно легко изменить количество используемых потоков. Например: вы можете создать пул потоков, в котором количество потоков определяется конфигурацией. Так что если вы хотите изменить количество потоков, вам нужно изменить только некоторые свойства.

О вашем вопросе:
- О чтении вашего сокета: Насколько я знаю, бесполезно (если вообще возможно) иметь два потока, считывающих данные из одного сокета. Просто используйте один поток, который читает сокет, но сделайте в этом потоке как можно меньше действий (например, прочитайте сокет - поместите данные в очередь - прочитайте сокет - и т. Д.).
- О потреблении очереди: Целесообразно построить эту часть, как указано выше, чтобы было легко изменить количество потребляющих потоков.
- Примечание: вы не можете предсказать, что лучше, может быть другая часть, которая является узким местом, и так далее. Только монитор / профилирование дает вам реальное представление о вашей ситуации. Но если ваше приложение построено так, как описано выше, его действительно легко протестировать с различным количеством потоков.

Короче говоря:
- Часть производителя : один поток, который читает только из сокета и помещает в очередь
- Consumer part : создан вокруг ExecutorService, поэтому легко адаптировать количество потребляющих потоков
Затем с помощью профилирования определите узкие места и используйте A-B-тестирование, чтобы определить оптимальное количество потребляющих потоков для вашей системы

1 голос
/ 18 августа 2010

Очень вероятно, что многопоточность поможет, но это легко проверить.Сделайте это настраиваемым параметром.Узнайте, сколько вы можете сделать в секунду: 1 поток, 2 потока, 4 потока, 8 потоков и т. Д.

1 голос
/ 18 августа 2010

Может ли один поток идти в ногу с поступающими данными?Может ли база данных идти в ногу с исходящими данными?

Другими словами, где узкое место?Если вам нужно использовать многопоточность, посмотрите на концепцию Executor в параллельных утилитах (в классе помощников Executors есть из чего выбирать), так как он будет обрабатывать все утомительные детали с многопоточностью, которые вам не особенно интересны.

Мое личное инстинктивное ощущение - узкое место в базе данных.Здесь очень помогает индексация и ОЗУ, но это другой вопрос.

0 голосов
/ 22 августа 2010

В вашем сценарии, где а) обработка минимальна б) имеется только один ЦП в) данные поступают прямо в базу данных, маловероятно, что добавление большего количества потоков поможет.Другими словами, передний и внутренний потоки связаны I / O с минимальной обработкой в ​​середине.Вот почему вы не видите большого улучшения.

То, что вы можете сделать, это попытаться выполнить три этапа: 1-й - это один поток, извлекающий данные из сокета.2-й пул потоков, который выполняет обработку.3-й является одним потоком, который обслуживает вывод БД.Это может привести к лучшей загрузке ЦП, если скорость ввода изменяется, за счет временного увеличения очереди вывода.Если нет, пропускная способность будет ограничена скоростью, с которой вы можете записывать в базу данных, независимо от того, сколько у вас потоков, а затем вы можете обойтись только одним потоком чтения-процесса-записи.

0 голосов
/ 19 августа 2010

Как обновление моего предыдущего вопроса:

Мы выполнили несколько сравнительных тестов между одним потребительским потоком и несколькими потоками (добавление 5, 10, 15 и т. Д.) И отслеживали размер очереди, пока не выполнено-обработанные записи.Разница была минимальной, и более того ... размер очереди становился немного больше после того, как число потоков пересекало 25 (по сравнению с выполнением 5 потоков).Приводит меня к выводу, что затраты на обслуживание потоков были больше, чем выгоды от обработки.Может быть, это может быть специфическим для нашего сценария, но просто упомянуть мои наблюдения.

И, конечно, (как отмечают другие) узким местом является база данных.Это было обработано с помощью оператора множественной вставки в mySQL вместо одиночной вставки.Если бы у нас не было этого для начала, мы бы не справились с этой нагрузкой.

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

И снова спасибо за ваш вклад.

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