Здраствуйте!
У меня вот такая тема для разработки -
"Регулирование движения поездов на станции (Система массового обслуживания, потоки)"...
Т.е. можно сказать, что процессорное время (ресурс) - наша станция, тогда потоки - поезда.. и нужно распланировать использование этого ресурса...Но это всё общие фразы..
Объясните пожалуйста, как это должно выглядеть более конкретно..я пока не очень понимаю..
Может быть у кого-нибудь есть идеи, как это эту тему оформить в виде приложения...С чего вообще начать? Подскажите пожалуйста! Плохо себе представляю, как это должно выгдядеть в моём приложении, в этом и проблема...
Смотри... Я когда-то делал на форуме эмуляцию работы банка: есть клиенты пользователи, есть кассиры, очередь клиентов, и когда подходит очередь, клиент направляется к освободившемуся кассиру...
Можно сделать нечто подобное и здесь: есть "поезд", есть "путь", на который этот поезд можно поставить, и держать его там какое-то определенное время, и отправлять дальше; если свободных путей нет - то все поезда проходят мимо. Все действия (время прибытия поезда, время отправления) фиксируются в логе, возможно - сделать еще и визуализацию (скажем, какой-нибудь ListBox, в котором будет храниться информация о путях: "свободен"/"занят, кем занят, и когда освободится")...
При таком подходе можно потоками представлять пути, а "поезда" - сделать просто структуру, хранящую ID, число вагонов (это если тебе захочется помучиться, и сделать более приближенную к реальности программу: на путь можно поставить поезд только, если длина поезда не превышает длины пути), время стоянки. Можно и поезда реализовать потоками, хотя я бы этого не делал, смысла не вижу в этом, основное "действующее лицо" в твоей программе - это все-таки Станция, и соответственно, Путь. Поезд - это так, проходящее
Через рандомные промежутки времени генерируешь "поезд", пробегаешься по "путям" в поисках свободного и способного принять этот поезд, и направляешь поезд на подходящий путь...
Только непонятно, что делать, если подходящих путей нет? Что, просто пропускать поезд на следующую станцию, пусть с ним там разбираются?
Или тебе нужно нечто совсем другое?
Мне убедительно посоветовали выбрать несколько иной подход:
есть станция, для неё предусмотрено n-е количество мест для стоянки проходящих поездов (для определённости - 3 места, например, для реализации этой идеи использовать семафор с максимальным количеством ресурсов=3).
Если все места заняты - поезд (это будет поток) должен ожидать освобождения места для стоянки (т.е. поезд на время ожидания засыпает). Главная цель - не пропустить поезд на станцию, если там нет свободных мест.
Для поезда, который занял своё место на станции - его время простоя должно определяться по закону (экспоненциальному наверное - с тем смыслом, что чем дольше поезд простоял, тем выше вероятность, что скоро он отправится дальше и освободит место стоянки)
Потоки-поезда должны генерироваться по з-ну Пуассона.
Выходные данные: думаю представить статистику по простоям и по ожиданию освобождения места..
Пока не представляю себе, как должна выглядеть генерация потока-поезда по Пуассону..
тоже самое с временем простоя на станции...не знаю, как поезда-поток "заставить" остаться там на некоторое время (тоже определяемое по закону)..
Пока решила начать с того, что по рандому создавать поезда-потоки, в функции потока в зависимости от состояния семафора записывать на listbox идентификатор поезд и его состояние..Вот только выводятся поезда как попало...Даже не знаю, в чём причина может быть..
А вообще хочу представить движение-остановку поездов-потоков в виде передвижения-застывания label с каким-нибудь текстом..
DWORD TrainThread(int *p)
{
wsprintf(buf,L"Train #%d...",*p);
SendMessage(hListBox,LB_ADDSTRING, 0, (LPARAM)(LPCSTR)buf);
// Проверяем состояние семафора
DWORD dwResult = WaitForSingleObject(hSemaphore, 10000);
DWORD time_stopping;
switch(dwResult) {
case WAIT_OBJECT_0:
// Место есть, остановка
wsprintf(buf,L"Train #%d is stoping...",*p);
SendMessage(hListBox,LB_ADDSTRING, 0, (LPARAM)(LPCSTR)buf);
time_stopping = (rand() % 3000) + 1000; // Время стоянки
Sleep(time_stopping);
ReleaseSemaphore(hSemaphore, 1, NULL); // Освободим семафор
break;
case WAIT_TIMEOUT:
// Семафор занят, ожидаем ...
wsprintf(buf,L"Train #%d: no empty places...waiting",*p);
SendMessage(hListBox,LB_ADDSTRING, 0, (LPARAM)(LPCSTR)buf);
break;
}
return 0;
}
void OnClickButRun(HWND hwnd)
{
// генератор случ. чисел
srand(time(NULL));
if(hSemaphore = CreateSemaphore(NULL, maxPlaces, maxPlaces, NULL)) {
for(int i = 0; i < maxTrains; i++) {
trainID[i] = i+1;
trainHandles[i] = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)TrainThread,
&trainID[i], 0, NULL);
}
CloseHandle(hSemaphore);
}
else SendMessage(hListBox,LB_ADDSTRING, 0, (LPARAM)(LPCSTR)TEXT("Error by creation semaphore"));
}
DWORD TrainThread(int *p)
{
wsprintf(buf,L"Train #%d...",*p);
SendMessage(hListBox,LB_ADDSTRING, 0, (LPARAM)(LPCSTR)buf);
int finished = 0;
do {
// Проверяем состояние семафора
DWORD dwResult = WaitForSingleObject(hSemaphore, 1000); // !!! ждем 1 секунду
DWORD time_stopping;
switch(dwResult) {
case WAIT_OBJECT_0:
// Место есть, остановка
wsprintf(buf,L"Train #%d is stoping...",*p);
SendMessage(hListBox,LB_ADDSTRING, 0, (LPARAM)(LPCSTR)buf);
time_stopping = (rand() % 3000) + 1000; // Время стоянки
Sleep(time_stopping);
ReleaseSemaphore(hSemaphore, 1, NULL); // Освободим семафор
finished = 1;
break;
case WAIT_TIMEOUT:
// Семафор занят, сообщаем об этом, и повторяем попытку ...
wsprintf(buf, L"Train #%d: no empty places...waiting",*p);
SendMessage(hListBox,LB_ADDSTRING, 0, (LPARAM)(LPCSTR)buf);
break;
}
} while(!finished);
return 0;
}
WaitForMultipleObjects(maxTrains, trainHandles, TRUE, INFINITE); // дождаться всех
CloseHandle(hSemaphore); // и только теперь удалить семафор
Эх...а у меня не работает..приложение зависает..
изменила функцию потока..добавила ожидание завершения потоков..
void OnClickButRun(HWND hwnd)
{
// генератор случ. чисел
srand(time(NULL));
if(hSemaphore = CreateSemaphore(NULL, maxPlaces, maxPlaces, NULL)) {
for(int i = 0; i < maxTrains; i++) {
trainID[i] = i+1;
trainHandles[i] = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)TrainThread,
&trainID[i], 0, NULL);
}
WaitForMultipleObjects(maxTrains, trainHandles, TRUE, INFINITE); // дождаться всех
CloseHandle(hSemaphore);
}
else SendMessage(hListBox,LB_ADDSTRING, 0, (LPARAM)(LPCSTR)TEXT("Error by creation semaphore"));
}
int b = 1;
do {
// DWORD r = ; // дождаться всех
switch(WaitForMultipleObjects(maxTrains, trainHandles, TRUE, 100)) {
case WAIT_TIMEOUT:
// Здесь добавить аналог Application->ProcessMessages() чтоб обновить окно;
break;
default:
b = 0;
}
} while(b);
CloseHandle(hSemaphore);
WaitForMultipleObjects(maxTrains, trainHandles, TRUE, INFINITE); // дождаться всех
CloseHandle(hSemaphore);
DWORD TrainThread(int *p)
{
__int64 gTime;
QueryPerformanceCounter((LARGE_INTEGER *)&gTime);
srand(gTime);
// дальше функция потока
...
case WAIT_TIMEOUT:
// Здесь добавить аналог Application->ProcessMessages() чтоб обновить окно;
break;
.....
Тебе нужно заставить форму обработать полученные сообщения и элементарно перерисоваться, иначе ты ж ничего не увидишь... В Билдеровском VCL для этого используется метод Application->ProcessMessages(). Для чистого WinAPI, скорее всего, подойдет вот это:
case WAIT_TIMEOUT:
// Application->ProcessMessages();
MSG lpMsg;
while (PeekMessage(&lpMsg, NULL, 0, 0, PM_REMOVE)) {
TranslateMessage(&lpMsg);
DispatchMessage(&lpMsg);
}
break;
Спасибо большое!!
Теперь насчёт генерации потоков-поездов по Пуассоновскому з-ну..
Объясните пожалуйста, как это должно выглядеть..?? Я даже не представляю..Может потоки будут генерироваться по таймеру через промежутки времени, которые определяются в соответствии с з. Пуассона? или я не в том направлении думаю?
http://window.edu.ru/window_catalog/pdf2txt?p_id=11482&p_page=3 лежит
Да, все правильно... Ф-ю Puass можно использовать именно для генерации временных интервалов между созданием потоков.
int Puass(float Lamda)
{
float ver,p0,P;
int k;
k=0;
p0=exp(-Lamda);
P=p0;
__int64 gTime;
QueryPerformanceCounter((LARGE_INTEGER *)&gTime);
srand(gTime);
ver=rand();
do
{
ver=ver-P;
if (ver >= 0)
{
P=P*Lamda/(k+1);
k++;
}
}
while (ver<0);
return k;
}
if(hSemaphore = CreateSemaphore(NULL, maxPlaces, maxPlaces, NULL)) {
for(int i = 0; i < maxTrains; i++) {
trainID[i] = i+1;
SetTimer(hwnd,MY_TIMER,Puass(20000),NULL);
trainHandles[i] = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)TrainThread,
&trainID[i], 0, NULL);
}
int Puass(double Lamda)
{
int k = 0;
double p0 = exp(-Lamda);
double P = p0;
// Генерируем вещественное число в интервале 0 .. 1
double ver = (double)rand() / RAND_MAX;
do {
ver -= P;
if(ver >= 0) {
P = P*Lamda / (k+1);
k += 1;
}
} while(ver >= 0);
return k;
}
// А вот так будет выглядеть цикл генерации потоков:
// генератор случ. чисел, основной поток приложения
srand(time(NULL));
if(hSemaphore = CreateSemaphore(NULL, maxPlaces, maxPlaces, NULL)) {
for(int i = 0; i < maxTrains; i++) {
DWORD timeWait = Puass(9.5) * 10; // <--- Ну, коэффициенты сама подберешь
wsprintf(buf, "Ждем %ld ms перед генерацией следующего потока-поезда", timeWait);
SendMessage(hListBox, LB_ADDSTRING, 0, (LPARAM)(LPCSTR)buf);
// Ожидание, но все запущенные ранее потоки уже работают,
// на них Sleep не распространяется
Sleep(timeWait);
trainID[i] = i+1;
trainHandles[i] = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)TrainThread,
&trainID[i], 0, NULL);
}
здравствуйте!
скажите пожалуйста, а как сгенерировать время простоя поезда на станции по экспоненциальному з-ну?
т.е. вот здесь:
DWORD TrainThread(int *p)
{
__int64 gTime;
QueryPerformanceCounter((LARGE_INTEGER *)&gTime);
srand(gTime);
wsprintf(buf,L"Train #%d...",*p);
SendMessage(hListBox,LB_ADDSTRING, 0, (LPARAM)(LPCSTR)buf);
int finished = 0;
do {
// Проверяем состояние семафора
DWORD dwResult = WaitForSingleObject(hSemaphore, 1000); // !!! ждем 1 секунду
DWORD time_stopping;
switch(dwResult) {
case WAIT_OBJECT_0:
// Место есть, остановка
wsprintf(buf,L"Train #%d is stoping...",*p);
SendMessage(hListBox,LB_ADDSTRING, 0, (LPARAM)(LPCSTR)buf);
time_stopping = (rand() % 3000) + 1000; // !!!Время стоянки - нужно определить по эксп. з-ну
Sleep(time_stopping);
ReleaseSemaphore(hSemaphore, 1, NULL); // Освободим семафор
finished = 1;
break;
....
DWORD timeWait = Puass(9.5) * 10; // <--- Ну, коэффициенты сама подберешь
оу..прошу прощения..как-то упустила, что з-н Пуассона вполне экспоненциальный
Добавлено через 19 мин.
Хотелось бы теперь движение-остановку поездов-потоков представить графически...
Примерно так: поезд-поток (например в виде Label) подъехал к станции, есть места - переходит на свободное место стоянки (постоял некоторое время - уехал со станции), нет мест - ждёт перед станцией.
Подскажите пожалуйста, как соотнести задумку с уже имеющимся?
Прикрепленные файлы
main.cpp ( 7.59 килобайт )
Кол-во скачиваний: 265