|
Программирование >> Разработка устойчивых систем
fordelllt 1 = tellers. beginO: i != tellers.endO: i++) (*i).run(): cout { tellers.SizeO } customers endl: Если очередь слишком длинна, создаем нового кассира: if (customers. SizeO / tellers.sizeO > 2) tel1ers.push back(Tel 1er(customers)): Если очередь слишком коротка, убираем кассира: if(tellers.SizeO > 1 && customers. SizeO / tell ers. si zeO < 2) for(TellIt i = tellers.beginO: i != tellers.endO: i++) if(!(*i).isBusy()) { tellers.erase(i): break: Выход из цикла } III:- Каждому клиенту назначается определенное время обслуживания - количество квантов времени, которое должно быть потрачено кассиром на данного клиента. Время обслуживания определяется для каждого клиента случайным образом. Также мы не знаем, сколько клиентов будет поступать в каждый интервал, и эта величина также должна определяться случайным образом. Объекты Customer хранятся в очереди queue<Customer>. Каждый объект Teller содержит ссылку на эту очередь. Завершив обслуживание текущего объекта Customer, объект-кассир Teller берет из очереди новый объект клиента Customer и начинает обслуживание , то есть уменьшает время обслуживания Customer в течение каждого выделенного кванта. Вся логика обслуживания сосредоточена в функции run (). Фактически эта функция представляет собой команду if с выбором одного их трех вариантов: если время, необходимое для обслуживания клиента, меньше времени, оставшегося в текущем кванте кассира, равно или больше. Если после завершения работы с клиентом у кассира еще остается свободное время, он берет нового клиента и рекурсивно вызывает run(). Очередь, как и стек, не обладает функциональностью других базовых последовательных контейнеров. В частности, невозможно получить итератор для перебора элементов очереди. Тем не менее, последовательный контейнер, на базе которого реализована очередь, хранится в queue в виде защищенной переменной класса. В соответствии со стандартом С-ы- этой переменной присваивается имя с, а это означает, что для доступа к базовой реализации вы можете породить класс, производный от queue. Класс CustomerQ именно это и делает с единственной целью: определить операторную функцию ofstream operator для перебора очереди и вывода ее элементов. Все управление имитацией производится в цикле while функции main(). Цикл использует процессорные такты (см. <ctime>) для проверки того, что имитация продолжается минимум 5 секунд. В начале каждой итерации цикл генерирует случайное количество клиентов со случайными временами обслуживания. Программа выводит количество кассиров и содержимое очереди, чтобы вы могли оценить текущее состояние системы. После отработки каждого кассира программа снова выводит сведения о состоянии системы. В этот момент происходит автоматическая регулировка системы, для чего количество клиентов сравнивается с количе- ством кассиров. Если очередь стала слишком длинной, в системе создается новый кассир, а при недостаточной длине очереди кассир удаляется. Попробуйте поэкспериментировать с разными схема.ми подключения и удаления кассиров для достижения оптимального результата. Если в программе изменяется только эта часть, схему изменения числа кассиров стоит выделить в отдельный объект. Мы вернемся к этому примеру при рассмотрении многопоточности в главе И. Приоритетная очередь При занесении объекта в приоритетную очередь (контейнер priority queue) функцией push О позиция нового объекта определяется функцией сравнения или объектом функции (по умолчанию используется шаблон less, но вы также можете предоставить собственный критерий). Приоритетная очередь гарантирует, что верхний элемент очереди, возвращаемый функцией top(), обладает наибольшим значением (приоритетом). Когда все необходимые операции с элементом будут выполнены, верхний элемент выталкивается функцией рор(), а его место занимает следующий элемент. Таким образом, приоритетная очередь почти не отличается по интерфейсу от стека, но работает несколько иначе. Приоритетная очередь также относится к категории контейнерных адаптеров, работающих на базе последовательных контейнеров. По умолчанию в реализации priority queue используется вектор. Ниже приведен тривиальный пример приоритетной очереди для типа int: : C07:Prior1tyQueuel.cpp linclude <cstdlib> linclude <ctime> linclude <iostream> linclude <queue> using namespace std: int mainO { priority queue<int> pqi: srand(time(0)): Раскрутка генератора случайных чисел forCint i = 0: i < 100: i++) pqi.pushCrandC) % 25): whileC !pqi .emptyO) { cout pqi .topO : pqi.popC): } /:- Мы заносим в приоритетную очередь 100 случайных чисел от О до 24. При запуске этой программы становится видно, что наибольшие значения находятся на первых местах, и приоритетная очередь может содержать дубликаты. Следующий пример показывает, как изменить порядок следования элементов при помощи пользовательской функции или объекта функции. На этот раз наибольший приоритет назначается числам с минимальными значениями: : C07:PnorityQueue2.cpp Изменение приоритета linclude <cstdlib> linclude <ctime> linclude <functional> finclude <iostream> iinclude <queue> using namespace std: int mainO { pnority queue<int, vector<int>. greater<int> > pqi: srand(time(0)): for(int i - 0: i < 100: i++) pqi.push(rand() % 25): whi1e(!pqi.emptyО) { cout pqi .topO : pqi.popO: } /:- Более интересный пример - список задач, в котором каждый объект содержит строку с описанием задачи, а также два приоритета (первичный и вторичный): : C07:PnontyQueue3.cpp Нетривиальный пример приоритетной очереди linclude <iostream> linclude <queue> linclude <string> using namespace std: class ToDoItem { char primary: int secondary: string item: public: ToDoItemCstring td. char pri =A. int sec -1) : item(td). primary(pri). secondary(sec) {} friend bool operator<( const ToDoItemS x. const ToDoItemS y) { if(x.primary > y.primary) return true: if(x.primary = y.primary) if(x.secondary > y.secondary) return true: return false: friend ostreamS operator (ostream& os. const ToDoItem& td) { return os td.priтагу td.secondary : td.item; int mainO { priority queue<ToDoItem> toDoList: toDoLiSt.push(To[)oItem( Empty trash , C. 4)): toDoList.pushdoDoItemrFeed dog . A. 2)): toDoLiSt.push(ToDoItem( Feed bird . B . 7): toDoList.push(ToDoItem( Mow lawn . C. 3)); toDoLiSt.push(ToDoItem( Water lawn . A. D): to[)oList.push(ToDoIteffl( Feed cat , B. D); whiledtoDoList.emptyO) { cout toDoList.topO endl: toDoList.popO: } /:-
|
© 2006 - 2024 pmbk.ru. Генерация страницы: 0
При копировании материалов приветствуются ссылки. |