2012-04-24 4 views
0

У меня есть параллельная очередь соединений. Существует задача ping, которая периодически проходит через все доступные подключения в очереди для выполнения пинга, и в то же время приложение может запросить подключение из очереди для его использования.Обнаружение круговой петли в параллельной очереди

Что такое хороший способ обнаружения круговой петли, чтобы задача ping могла завершить свое выполнение?

РЕДАКТИРОВАТЬ:

Пример: Предположим, параллельную очередь имеет соединения А, В и С.

Существует пинг задача, которую итерацию по очереди. Таким образом, в этом примере он будет делать A.ping(), B.ping() и C.ping(). Теперь есть внешний класс, который также запрашивает соединение из очереди, в то время как задача ping также выполняет итерацию по очереди. Итак, предположим, что A.ping() закончил, и externalClass.getConnection() вернется A. К тому времени, когда задача ping заканчивается C.ping(), происходит externalClass.releaseConnection(A). Теперь заказ очереди B,C and A. Таким образом, задача ping снова найдет A после завершения C.ping(), в этот момент задача должна решить A уже была проверена и должна завершить текущее выполнение.

+0

Просьба привести примерное обстоятельство, когда происходит циклическая петля – HelloWorld

+0

Отредактировано с помощью примера – Prasanna

ответ

0

Выполняет ли ваш пинг только ping на каждой машине, или он пингует одну машину, которая пингует следующую, которая пинает следующую, а затем и так далее?

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

Другим способом решения этой проблемы является передача информации о том, какие машины уже рассматривал данный пакет ping вместе с ним, а когда пакет ping достигает уже увиденного, он завершается.

+0

Пул соединений имеет все подключения к одному и тому же компьютеру, что означает, что все соединения выполняются на одной машине. – Prasanna

+0

Так в чем же проблема? Отскакивает ли машина назад, когда вы ее пингуете, или что? Каково ваше значение круговой петли? – moowiz2020

1

Для начала у вас нет круговой петли.

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

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

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

С учетом сказанного, что-то очень не так с вашей очередью, если у вас могут быть два разных абонента, получающих одинаковый результат A в очереди.

Правильный способ выполнения этого кода состоит в том, чтобы иметь два отдельных списка, один из которых представляет собой очередь соединений для запросов, таких как externalClass.getConnection(), а другой список соединений для Ping.Независимо от Ping операции делает это на самом деле ничего такого, что любой внешний класс делает с ним не должно повлиять на это соединение, например предполагающей connection является sql connection то Ping должен выполнить что-то вроде этого:

SELECT TOP 1 1 

И больше ничего, что будет означать, что ваше соединение остается в живых. поскольку вы, скорее всего, реализуете это, потому что соединения простаивают слишком долго и закрываются сами .., в этом случае вы действительно не должны, потому что в значительной степени любой вкус sql dbms поддерживает объединение пулов, которое делает именно то, что вы пытаетесь сделать. Если вы не хотите предотвратить одновременное одновременное соединение с Queue.Count одновременно, ожидая других ожиданий (что само по себе может быть сделано гораздо лучше, если поддерживать пул открытых соединений, например простой int counter)

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

Но для полноты в ответ на ваш вопрос:

Если вы сделал имеют круглую петлю он будет выглядеть следующим образом: A -> B -> C -> A, где каждый элемент будет указывать на следующий в списке, а не просто элементов в queue. Хорошим примером может служить вы пинг сервера A который пингует сервер B который пингует сервер C который затем свистит A и вы бы обнаружить его следующим образом:

Простой способ обнаружения круговых петель является запуск двух (или нескольких) итераций через него мы назовем их X и Y.

Для каждого второго шага (или .Ping() в вашем контексте) X, вы шаг Y один раз. Возможно, вы захотите сделать новый метод, например Visit, вместо того, чтобы называть ваш Ping так, чтобы ping не вызывался много раз в цикле.

Предполагая, что очередь выглядит A, B, C, A, B...

После нескольких шагов X будет выглядеть так: A, B, C, A в то время как Y будет выглядеть A, B. Что вы делаете, так это то, что вы не сохраните всю историю, вы только посмотрите на текущие значения, поэтому, когда вы ступите в X, вы проверяете, соответствует ли новое значение текущему значению Y, таким образом, мы, в конечном счете, всегда получим столкновение.

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

Но вы можете улучшить производительность в среднем, только расширяя это еще иметь Z итератор, который ступает один раз на каждые три X шагов, на данный момент это не на самом деле стоит добавить еще одну программу, которая ступает через каждые 5 X шагов или 7 и и так далее (посещение следующего инкрементного простого числа с созданием каждого нового итератора).

+0

Соединения не являются соединением JDBC, но бережливые соединения и ping() - метод бережливого обслуживания. И да, на данный момент я использую решение, подобное вашему предложению, используя HashSet вместо HashTable. Но мне трудно понять ваше объяснение использования 2 списков. Я хочу, чтобы открытые соединения были сохранены, чтобы он мог использоваться внешним классом. – Prasanna

0

Возможно, я не понимал, что вы там делаете, но для меня это похоже на проблему, потому что задача Ping не соответствует правилу enqueue/dequeue, как это делает внешняя задача. Итак, как насчет того, чтобы Ping Task сначала удалила соединение, обновите его «значение ping» и затем верните его обратно?

Если ваша цель состоит в том, чтобы гарантировать, что внешняя задача всегда получает соединение с наименьшим значением ping, вы можете захотеть использовать кучу вместо очереди.

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