Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Методичка курсовые АТП-41.doc
Скачиваний:
0
Добавлен:
01.04.2025
Размер:
245.25 Кб
Скачать

Описание методов решения и алгоритмов задач, реализуемых каждым потоком

В основной программе вводим размер массива N и время вывода T.

Работа первого потока заключается в следующем:

  1. Ждем время T;

  2. Если заполнили весь массив – переходим к п.9;

  3. Входим в критическую секцию;

  4. Увеличиваем размер массива;

  5. Добавляем случайный элемент;

  6. Выводим элемент;

  7. Выходим из критической секции;

  8. Переходим к п. 2;

  9. Завершаем поток.

Работа второго потока заключается в следующем:

1. Если дошли до конца массива – переходим к п. 7;

2. Если требуемые элементы еще не заполнены потоком A – п. 2 (ждем);

3. Берем два подряд идущих числа. Считаем их x и y;

4. Рассчитываем расстояние до начала координат. Накапливаем расстояние;

5. Выводим среднее расстояние из уже рассчитанных;

6. Наращиваем счетчик на 2. Переходим к п.1;

7. Завершаем поток.

Работа третьего потока заключается в следующем:

1. Если дошли до конца массива – переходим к п. 7;

2. Если требуемые элементы еще не заполнены потоком A – п. 2 (ждем);

3. Берем текущий элемент массива и находим минимальное и максимальное значение между ним и уже найденными до сих пор;

4. Рассчитываем процент;

5. Выводим Min, Max и процент;

6. Наращиваем счетчик на 1. Переходим к п. 1;

7. Завершаем поток.

Описание методов создания, синхронизации и уничтожения потоков

Поток А.

Класс потока имеет следующую структуру.

TAThread = class(TThread)

public

constructor Create(CreateSuspended: Boolean);

destructor Destroy; override;

protected

procedure Execute; override;

end;

Создание потока осуществляется в конструкторе Create, параметром которого служит переменная CreateSuspended, позволяющая сразу запустить поток или оставаться в приостановленном состоянии.

В конструкторе совершаются следующие действия.

constructor TAThread.Create(CreateSuspended: Boolean);

begin

inherited; // Запуск родительского конструктора

SetLength(Mas, 0); // Подготовка массива

Randomize; // Инициализация случайных чисел

end;

В деструкторе происходят следующие действия.

destructor TAThread.Destroy;

begin

SetLength(Mas, 0); // Удаление массива из памяти

Mas := nil;

inherited; // Вызов родительского деструктора

end;

В процедуре обработки потока происходят следующие действия.

procedure TAThread.Execute;

begin

repeat

Sleep(T); // Устанавливаем задержку в мс

if Length(Mas) < N then // Если не превысили размер массива

begin

Section.Enter; // Входим в критическую секцию

SetLength(Mas, Length(Mas) + 1); // Увеличиваем размер массива

Mas[Length(Mas) - 1] := -999 + Random(1999); //Заносим случайное число

GotoXY(0, Length(Mas) + 4); //Устанавливаем курсор в нужную позицию

Write(Mas[Length(Mas) - 1]: 4); // Выводим элемент

Section.Leave; // Выходим из критической секции

end

else

Terminate; // Если превышен размер массива – завершаем поток

until Terminated;

end;

Здесь необходима критическая секция, так как в этом фрагменте изменяется размер массива, который используется потоками B и C. Поэтому важно не допустить эти потоки к массиву, пока он изменяется, чтобы избежать случаев, когда размер массива изменен, а, например, новое число в него еще не внесено.

Поток B.

Класс потока имеет следующую структуру.

TBThread = class(TThread)

public

constructor Create(CreateSuspended: Boolean);

protected

procedure Execute; override;

end;

Создание потока осуществляется в конструкторе Create, параметром которого служит переменная CreateSuspended, позволяющая сразу запустить поток или оставаться в приостановленном состоянии.

В конструкторе совершаются следующие действия.

constructor TBThread.Create(CreateSuspended: Boolean);

begin

inherited; // Запуск родительского конструктора

CurB := 0; // Устанавливаем текущую позицию в массиве

Dist := 0; //Подготавливаем переменную для хранения расстояний

end;

В процедуре обработки потока происходят следующие действия.

procedure TBThread.Execute;

begin

repeat

if CurB = N then // Если дошли до конца массива – завершаем работу

Terminate;

if CurB <= Length(Mas) - 2 then // Следуем по массиву с шагом два (координата x и y)

begin

{ Вычисляе расстояние от точки до начала координат }

Dist := Dist + Sqrt(Sqr(Mas[CurB]) + Sqr(Mas[CurB + 1]));

{ Выводим }

GotoXY(15, CurB + 6); Write('Dist=', Dist / (CurB + 2): 6: 4);

{ Переходим к следующим координатам }

Inc(CurB, 2);

end;

until Terminated;

end;

Поток C.

Класс потока имеет следующую структуру.

TCThread = class(TThread)

public

constructor Create(CreateSuspended: Boolean);

protected

procedure Execute; override;

end;

Создание потока осуществляется в конструкторе Create, параметром которого служит переменная CreateSuspended, позволяющая сразу запустить поток или оставаться в приостановленном состоянии.

В конструкторе совершаются следующие действия.

constructor TBThread.Create(CreateSuspended: Boolean);

begin

inherited; // Запуск родительского конструктора

CurC := 0; // Устанавливаем текущую позицию в массиве

Max := -1000; // Настраиваем Min и Max. Ставим для Max заведомо меньшее из чисел, а для Min – заведомо большее

Min := 1000;

end;

В процедуре обработки потока происходят следующие действия.

procedure TBThread.Execute;

var

Proc: double;

begin

repeat

if CurC = N then // Если достигнут конец массива – завершаем поток

Terminate;

if CurC < Length(Mas) then // Не должны считать элементы, которые еще не заполнены.

begin

Inc(CurC);

{ Находим Min и Max среди уже найденных и текущим элементом}

if Min > Mas[CurC - 1] then

Min := Mas[CurC - 1];

if Max < Mas[CurC - 1] then

Max := Mas[CurC - 1];

if Max = Min then

Proc := 0 // Для первого элемента = 0, так как изначально Min=Max

else

Proc := Mas[CurC - 1] / (Max - Min);

{ Выводим }

GotoXY(35, CurC + 4); Write('Max=', Max: 4);

GotoXY(50, CurC + 4); Write('Min=', Min: 4);

GotoXY(65, CurC + 4); Write('Proc=', Abs(Proc * 100):6:3, '%');

end;

until Terminated;end;

В основной программе мы создаем объекты-потоки.

ThreadA := TAThread.Create(true);

ThreadB := TBThread.Create(true);

ThreadC := TCThread.Create(true);

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

ThreadA.FreeOnTerminate := true;

ThreadB.FreeOnTerminate := true;

ThreadC.FreeOnTerminate := true;

Устанавливаем приоритет потоков.

ThreadA.Priority := tpIdle;

ThreadB.Priority := tpIdle;

ThreadC.Priority := tpIdle;

Запускаем потоки.

ThreadA.Resume;

ThreadB.Resume;

ThreadC.Resume;