Стандартная тактика

14 апреля 2008 года, 16:31

Иногда при разработке той или иной системы возникает такая ситуация, как синхронизация вполне себе асинхронного получения данных и вывода таких данных на экран (в приложение, если быть более скурпулёзным). Такая проблема часто встречается при разработке сетевых приложений с графическим интерфейсом и «заширменной частью».

Такие приложения очень часто разводятся по следующим частям:
  • сервис, который отвечает за мониторинг информации в сети
  • монитор сервиса, который будет по мере прихода данных в специальный буффер получать их оттуда и отдавать пользовательскому интерфейсу
  • пользовательский интерфейс, который будет принимать необходимые данные и выводить их пользователю

В самом простом случае каждой части соответствует отдельный поток выполнения и они выполняются параллельно. Сегодня мы постараемся рассмотреть самый простой способ синхронизации входящих и исходящих данных — использование промежуточного буффера для приёма и отдачи набора величин.

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

Для начала создадим базовый класс для всех наших операций:

class Connector #Создаём инициализатор класса def initialize end #Клиент def client end #Передатчик def server end end

Теперь сделаем конструктор нашего класса:

#Создаём инициализатор класса def initialize #Промежуточный буффер @buffer = [] #Создаём поток клиента client_thread = Thread.new do self.client end #Создаём поток сервера server_thread = Thread.new do self.server end server_thread.join end

Для начала мы сымитируем непостоянный и разбросанный приход данных от сервера (работаем в метода server):

#Передатчик def server #Бесконечный цикл while true #Добавляем в конец буффера-массива случайно число @buffer.concat([ rand(100) ]); #Ждём свободное число секунд sleep( rand(10) ) end end

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

#Клиент def client while true #Проверяем, есть ли в буффере входящие данные if @buffer != nil and @buffer.size > 0 #Выводим содержимое буффера puts @buffer.join( "," ) #Очищаем буффер @buffer.clear else #Выводим сообщение об отсутствии данных puts "Nothing new" end #Ждём ровно 5 секунд sleep 5 end end

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

В данной реализации мы столкнулись с временным буффером, так как без него обойтись было бы достаточно трудно: два разных потока в абсолютно разное время добавляют/считывают информацию из одной и той же переменной. Если бы в буффере были какие-либо ограничения на размер входящих данных, то могли бы возникнуть так называемые «deadlocks», то есть ситуации, когда и клиент не может работать с данными, так и сервер не может обработать потом исходящих величин.

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

Мнения (0)

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

Не оставлено никаких мыслей к статье. Не желаете ли?

Я тоже знаю!

Вы можете тоже написать собственный комментарий. Если хотите к кому-то обратиться, используйте символ @, после которого не забудьте написать имя того, к кому обращаетесь. Не забывайте про существование XHTML-элементов, с помощью которых вы можете оформить ваш комментарий как вам угодно. И, да: ведите себя достойно, вы же не роботы, правда? Если вам интересно, можете подписаться на комментарии по RSS.