3121

Написание программы реализующей параллельную работу нескольких процессов

Курсовая

Информатика, кибернетика и программирование

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

Русский

2012-10-24

121.5 KB

18 чел.

Необходимо написать программу, реализующую параллельную работу нескольких процессов. Каждый процесс может состоять из одного или нескольких потоков. Любой из потоков, работающих в составе этих процессов, может быть приостановлен и вновь запущен некоторой определенной клавишей (можно использовать буквенные или цифровые клавиши). Нажатия клавиш обрабатывать с помощью прерывания от клавиатуры (по материалам лаб. работы №1).

Окончание работы программы должно происходить при приостановке всех потоков их ключевыми клавишами либо при нажатии клавиши ESC. При окончании работы необходимо выполнить корректное завершение, т.е. “дочитать” всю информацию из буфера каждого процесса (при его наличии), закрыть все открытые файлы и т.п. – по материалам лаб. работы №4.

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

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

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

Задачи 1, 3, 6 предполагают наличие управляющего блока, который, используя прерывания таймера, случайным образом определяет очередной активный поток и выделяет ему кванты времени (возможно, в рамках большего кванта, выделенного всему процессу). Кванты времени – как для процесса в целом, так и для его потоков – изначально задавать некоторой фиксированной величины, но предусмотреть возможность её изменения во время работы путем нажатия некоторых ключевых клавиш (для каждого из потоков предусмотреть свою клавишу) – т.е. можно, например, увеличить или уменьшить квант только потока-пpоизводителя. При этом допустимы разные варианты реализации – “общий” квант может либо меняться, либо оставаться постоянным (тогда при ускорении одного потока другой автоматически замедлится, т.к. величина его кванта уменьшится).

Потоки этого класса задач могут иметь три статуса: “активен”, “ожидает” или “приостановлен”. В процессе работы может возникнуть, например, следующая ситуация. Поток-потребитель приостановлен своей ключевой клавишей, следовательно, буфер не освобождается. Поток-производитель активен, он заполнит буфер информацией и перейдёт в состояние ожидания. Из этого состояния он сможет выйти только после того, как будет возобновлена (нажатием клавиши) работа потока-потребителя, который освободит место в буфере для помещения новой информации. В случае приостановки производителя возникнет аналогичная ситуация, только с пустым буфером. Приостановка/возобновление потока возможны в любом его состоянии – как в активном, так и в состоянии ожидания.

Задачи 2, 4, 5, 7 должны выполняться равномерно, независимо от степени загрузки системы. Для этого каждой из них необходимо получать управление через фиксированное количество “тиков” системного таймера, во время которого они выполнят какое-то свое элементарное действие (“бегущая строка” или “летающий объект” сместится на одну позицию, сменится нота в музыке…). При такой реализации скорость каждого потока будет определяться количеством “тиков” таймера между его запусками. Для уменьшения скорости такого потока достаточно после нажатия ключевой клавиши предоставлять ему управление реже, через большее число “тиков”, соответственно для ускорения такого потока – опять же после нажатия ключевой клавиши – ему предоставляется управление чаще, в пределе – на каждом “тике”. Так, “бегущая строка” должна двигаться равномерно с постоянной скоростью (если она не приостановлена ключевой клавишей) независимо от количества активных процессов в системе, музыка – тоже играть равномерно… Потоки этого класса задач могут иметь два статуса: “активен” и “приостановлен”.

Задания:

3. Два потока: один выполняет поиск всех последовательных простых чисел и заносит их в буфер, второй осуществляет их вывод из буфера на экран (по материалам лаб. работы №4).

4. Вывод заголовка работы (фамилия и имя автора, название работы) постоянно меняющегося цвета. Место вывода (верхняя или нижняя строка), задавать в качестве параметра командной строки.

6. Два потока: один генерирует случайные числа и выбирает в буфер те, которые являются полным квадратом, второй – выводит их из буфера на экран (по материалам лаб. раб. №4).

7. Движущийся объект (в простейшем случае, например, летающий и отражающийся от границ шарик). Движение может осуществляться свободно или при управлении с клавиатуры (по материалам лаб. работы №5).
Параметры командной строки.

Программа принимает один параметр – положение заголовка (a – вверху, b – внизу).

Описание основных алгоритмов, используемых в программе.

Вывод заголовка и летающий квадрат реализованы как фоновые процессы. Изменяют свой вид эти объекты благодаря генератору случайных чисел.

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

Для поиска простых чисел используется следующий алгоритм. Берем число из переменной Num (изначально там записана единица) и прибавляем к нему единицу до тех пор, пока оно не станет простым. Для проверки на простоту числа используется отдельная булева функция PrimeNumber. Найденное число заносится в буфер. Проверка на наличие свободного места в буфере находится в начале процедуры, поэтому, если в буфере нет свободного места, то поток переходит в состояние ожидания и новых простых чисел не ищет. Любое простое число, помещенное в буфер, не превосходит константы MaxLongint. Поиск простых чисел продолжается до тех пор, пока не истечет время, отведенное на работу данного потока. Поток печати простых чисел проверяет буфер на пустоту и, если буфер не пуст, то извлекает первое число из буфера и выводит его на экран. Если буфер пуст, то поток переходит в режим ожидания.

Описание основных переменных, констант и типов.

В программе для фиксирования состояний (статусов) процессов и потоков определён следующий тип:

type Status = (Assigned, Wait, Suspended);

Константы.

Title – текст заголовока;

TitleRefresh –  период смены цвета заголовка;

Buf1Len – размер буфера первого процесса;

Buf2Len – размер буфера второго процесса;

Delay1 – задержка для первого процесса;

Delay2 – задержка для второго процесса;

StrLen – длина строки окна вывода;

Kill – флаг завершения программы;

SquareRefresh – период движения квадрата;

TPos – положение заголовка.

Переменные.

OldTHandler, OldKHandler – старые обработчики прерываний;

Scr – массив для прямого доступа к видеопамяти;

T, T1, T2 – счётчики времени таймер;

Thread – состояния потоков;

Buf1 – буфер первого процесса;

Buf2 – буфер второго процесса;

Top1, Top2 – вершины буферов;

Time – дополнительные времена для потоков;

CurThread – номер текущего активного потока;

X1, Y1, X2, Y2 – координаты экрана для вывода сгенерированных чисел;

SX, SY – координаты квадрата;

dx, dy – «направляющие» квадрата;

tmp_symbol, tmp_attr – перекрытая квадратом часть экрана;

Num – полученное простое число.

Описание подпрограмм.

Print – процедура вывода строки на экран;

Fly – процедура сдвига летающего квадрата;

THandler – обработчик прерываний таймера;

PrintStatus – вывод на экран состояния заданного потока;

ChangeStatus – изменение состояния заданного потока;

Prod1, Cons1, Prod2, Cons2 – процедуры потоков потребителей и производителей;

PrimeNumber – функция проверки числа на простоту;

KHandler – обработчик прерываний клавиатуры;

SetCurSize – процедура изменения размера курсора;

Initialize – инициализирует основные переменные;

KillProc – процедура завершения работы программы.

Работа программы (снимок экрана).


Исходный код программы.

program solution;

{$M $1024, 0, 0}

uses

 Crt, Dos;

type

 Status = (Active, Waits, Suspended); { Состояния потока }

const

 Title = 'Заголовок'; { Текст заголовка }

 TitleRefresh = 10;  { Период смены цвета заголовка   }

 Buf1Len = 13;       { Размер буфера первого процесса }

 Buf2Len = 13;       { Размер буфера второго процесса }

 Delay1 = 10000;     { Задержка для первого процесса  }

 Delay2 = 10000;     { Задержка для второго процесса  }

 StrLen = 39;        { Длина строки окна вывода       }

 Kill: Boolean = False; { Флаг завершения программы   }

 SquareRefresh = 2;  { Период движения квадрата       }

 TPos: Byte = 1;

var

 OldTHandler, OldKHandler: Procedure; { Старые обработчики прерываний }

 Scr: Array[1..25, 1..80] of Record   { Массив для прямого доступа к видеопамяти }

   Symbol: Char;

   Attr: Byte;

 end Absolute $B800:$0000;

 T, T1, T2: Word;      { Счётчики времени таймера }

 Thread: Array[1..6] of Status;    { Состояния потоков }

 Buf1: Array[1..Buf1Len] of Word;  { Буфер первого процесса }

 Buf2: Array[1..Buf2Len] of Longint; { Буфер второго процесса }

 Top1, Top2: Word;                          { Вершины буферов }

 Time: Array[1..4] of Byte;  { Дополнительные времена для потоков }

 CurThread: Byte;            { Номер текущего активного потока    }

 X1, Y1, X2, Y2: Byte; { Координаты экрана для вывода сгенерированных чисел }

 F: Text;         { Файл с текстом }

 SX, SY: Byte;    { Координаты квадрата     }

 dx, dy: Integer; { "Направляющие" квадрата }

 tmp_symbol: Array[0..1, 0..1] of Char; { Перекрытая квадратом часть экрана }

 tmp_attr: Array[0..1, 0..1] of Byte;

 Num: Longint;

{ Вывод строки S на экран начиная с i-го столбца, j-й строки цветом Color }

procedure Print(const S: String; const i, j: Byte; const Color: Byte);

var

 k: Integer;

begin

 if i + Length(S) - 1 > 80 then Exit;

 for k := i to i + Length(S) - 1 do begin

   Scr[j, k].Attr := Color;

   Scr[j, k].Symbol := S[k - i + 1];

 end;

end;

{ Сдвигает летающий квадрат }

procedure Fly;

var

 i, j: Integer;

begin

 while (SX + dx > 64) or (SX + dx < 45) or (SY + dy > 22) or (SY + dy < 3) do

 begin

   case Random(4) of

     0: dx := -1;

     1: dx := 1;

     2: dx := 2;

     3: dx := -2;

   end;

   case Random(4) of

     0: dy := -1;

     1: dy := 1;

     2: dy := 2;

     3: dy := -2;

   end;

 end;

 for i := 0 to 1 do

   for j := 0 to 1 do

   begin

     Scr[SY + j, SX + i].Attr := tmp_attr[j, i];

     Scr[SY + j, SX + i].Symbol := tmp_symbol[j, i];

   end;

 SX := SX + dx;

 SY := SY + dy;

 for i := 0 to 1 do

   for j := 0 to 1 do

   begin

     tmp_attr[j, i] := Scr[SY + j, SX + i].Attr;

     tmp_symbol[j, i] := Scr[SY + j, SX + i].Symbol;

   end;

 for i := 0 to 1 do

   for j := 0 to 1 do

   begin

     Scr[SY + j, SX + i].Attr := LightGreen;

     Scr[SY + j, SX + i].Symbol := Chr(219);

   end;

end;

{ Обработчик прерываний системного таймера }

{$F+}

procedure THandler; Interrupt;

begin

 if Thread[1] = Active then begin

   Inc(T1);

   if T1 >= TitleRefresh then begin

     Print(Title, 40 - Length(Title) div 2, TPos, 1 + Random(15));

     T1 := 0;

   end;

 end;

 if Thread[2] = Active then begin

   Inc(T2);

   if T2 >= SquareRefresh then begin

     Fly;

     T2 := 0;

   end;

 end;

 Inc(T);

 Inline($9C);

 OldTHandler;

end;

{$F-}

{ Вывод на экран состояния i-го потока }

procedure PrintStatus(const i: Byte);

var

 _Y: Byte;

begin

 case Thread[i] of

   Active: Print('Активен    ', 66, 3 + i, LightGreen);

   Waits: Print('Ожидание   ', 66, 3 + i, Yellow);

   Suspended: Print('Остановлен ', 66, 3 + i, LightRed);

 end;

end;

{ Изменение состояния i-го потока }

procedure ChangeStatus(const i: Byte);

begin

 case i of

   1:

   begin

     if Thread[1] = Active then begin

       Thread[1] := Suspended;

       NoSound;

     end

     else

       Thread[1] := Active;

     PrintStatus(1);

   end;

   2:

   begin

     if Thread[2] = Active then Thread[2] := Suspended else Thread[2] := Active;

     PrintStatus(2);

   end;

   3:

   begin

     if Thread[3] <> Suspended then

       Thread[3] := Suspended

     else

       if CurThread = 0 then Thread[3] := Active else Thread[3] := Waits;

     PrintStatus(3);

   end;

   4:

   begin

     if Thread[4] <> Suspended then

       Thread[4] := Suspended

     else

       if CurThread = 1 then Thread[4] := Active else Thread[4] := Waits;

     PrintStatus(4);

   end;

   5:

   begin

     if Thread[5] <> Suspended then

       Thread[5] := Suspended

     else

       if CurThread = 2 then Thread[5] := Active else Thread[5] := Waits;

     PrintStatus(5);

   end;

   6:

   begin

     if Thread[6] <> Suspended then

       Thread[6] := Suspended

     else

       if CurThread = 3 then Thread[6] := Active else Thread[6] := Waits;

     PrintStatus(6);

   end;

 end;

end;

{ Поток-производитель первого процесса (генерация чисел) }

procedure Prod1(const TMax: Byte);

var

 Z: String[5];

 Num: Word;

begin

 if Thread[3] = Suspended then Exit;

 if (Thread[3] = Waits) and (Top1 <> Buf1Len) then Thread[3] := Active;

 if Thread[3] = Active then begin

   Print('   ', 66, 11, White);

   Str(TMax, Z);

   Print(Z, 66, 11, White);

 end;

 PrintStatus(3);

 T := 0;

 while (T <= TMax + Time[1]) and (Thread[3] <> Suspended) do begin

   if Top1 = Buf1Len then begin

     Thread[3] := Waits;

     PrintStatus(3);

     Break;

   end;

   repeat

     Num := Random(6000);

   until Frac(Sqrt(Num)) < 1e-6;

   Inc(Top1);

   Buf1[Top1] := Num;

   Str(Top1 / Buf1Len * 100:2:2, Z);

   Print(Z + ' %   ', 66, 16, White);

   Delay(Delay1);

 end;

 if Thread[3] = Active then Print('Время вышло', 66, 6, LightGray);

 Print(' - ', 66, 11, White);

end;

{ Поток-потребитель первого процесса }

procedure Cons1(const TMax: Byte);

var

 i, j: Integer;

 S: String;

begin

 if Thread[4] = Suspended then Exit;

 if (Thread[4] = Waits) and (Top1 <> 0) then Thread[4] := Active;

 if Thread[4] = Active then begin

   Print('   ', 66, 12, White);

   Str(TMax, S);

   Print(S, 66, 12, White);

 end;

 PrintStatus(4);

 T := 0;

 while (T <= TMax + Time[2]) and (Thread[4] <> Suspended) do begin

   if Top1 = 0 then begin

     Thread[4] := Waits;

     PrintStatus(4);

     Break;

   end;

   Str(Buf1[1]: 4, S);

   if X1 + Length(S) > StrLen then begin

     X1 := 0;

     if Y1 = 8 then begin

       for i := 3 to 10 do

         for j := 3 to 41 do

           Scr[i, j].Symbol := Scr[i + 1, j].Symbol;

       for j := 3 to 41 do

         Scr[11, j].Symbol := ' ';

     end

     else Inc(Y1);

   end;

   Print(S, 3 + X1, 3 + Y1, White);

   Inc(X1, Length(S) + 2);

   Dec(Top1);

   for i := 1 to Top1 do

     Buf1[i] := Buf1[i + 1];

   Str(Top1 / Buf1Len * 100:2:2, S);

   Print(S + ' %   ', 66, 16, White);

   Delay(Delay1);

 end;

 if Thread[4] = Active then Print('Время вышло', 66, 7, LightGray);

 Print(' - ', 66, 12, White);

end;

{ Возвращает True, если число x - простое }

function PrimeNumber(const x: Longint): Boolean;

var

 i: Integer;

 u: Longint;

begin

 PrimeNumber := False;

 if x <= 1 then Exit;

 for i := 2 to Trunc(Sqrt(x)) do

   if x mod i = 0 then Exit;

 PrimeNumber := True;

end;

{ Поток-производитель второго процесса (текс из файла) }

procedure Prod2(const TMax: Byte);

var

 i: Integer;

 c: Char;

 Z: String[8];

begin

 if Thread[5] = Suspended then Exit;

 if (Thread[5] = Waits) and (Top2 <> Buf2Len) then Thread[5] := Active;

 if Thread[5] = Active then begin

   Print('   ', 66, 13, White);

   Str(TMax, Z);

   Print(Z, 66, 13, White);

 end;

 PrintStatus(5);

 T := 0;

 while (T <= TMax + Time[3]) and (Thread[5] <> Suspended) do begin

   if Top2 = Buf2Len then begin

     Thread[5] := Waits;

     PrintStatus(5);

     Break;

   end;

   repeat

     Inc(Num);

   until PrimeNumber(Num) or (Num = MaxLongint);

   if Num = MaxLongint then Num := 2;

   Inc(Top2);

   Buf2[Top2] := Num;

   Str(Top2 / Buf2Len * 100:2:2, Z);

   Print(Z + ' %   ', 66, 17, White);

   Delay(Delay2);

 end;

 if Thread[5] = Active then Print('Время вышло' , 66, 8, LightGray);

 Print(' - ', 66, 13, White);

end;

{ Поток-потребитель второго процесса }

procedure Cons2(const TMax: Byte);

var

 i, j: Integer;

 Z: String[8];

 S: String;

begin

 if Thread[6] = Suspended then Exit;

 if (Thread[6] = Waits) and (Top2 <> 0) then Thread[6] := Active;

 if Thread[6] = Active then begin

   Print('   ', 66, 14, White);

   Str(TMax, Z);

   Print(Z, 66, 14, White);

 end;

 PrintStatus(6);

 T := 0;

 while (T <= TMax + Time[4]) and (Thread[6] <> Suspended) do begin

   if Top2 = 0 then begin

     Thread[6] := Waits;

     PrintStatus(6);

     Break;

   end;

   Str(Buf2[1]:10, S);

   if X2 + Length(S) > StrLen then begin

     X2 := 0;

     if Y2 = 10 then begin

       for i := 13 to 22 do

         for j := 3 to 41 do

           Scr[i, j].Symbol := Scr[i + 1, j].Symbol;

       for j := 3 to 41 do

         Scr[23, j].Symbol := ' ';

     end

     else Inc(Y2);

   end;

   Print(S, 3 + X2, 13 + Y2, White);

   Inc(X2, Length(S) + 2);

   Dec(Top2);

   for i := 1 to Top2 do

     Buf2[i] := Buf2[i + 1];

   Str(Top2 / Buf2Len * 100:2:2, Z);

   Print(Z + ' %   ', 66, 17, White);

   Delay(Delay2);

 end;

 if Thread[6] = Active then Print('Время вышло', 66, 8, LightGray);

 Print(' - ', 66, 14, White);

end;

{ Обработчик прерываний клавиатуры }

{$F+}

procedure KHandler; Interrupt;

var

 Local_Time: String[5];

begin

 case Port[$60] of

   1:  Kill := True;                    { нажата Esc }

   2:  if Time[1] > 0  then Dec(Time[1]);   { нажата 1 }

   3:  if Time[1] < 90 then Inc(Time[1]);   {        2 }

   4:  if Time[2] > 0  then Dec(Time[2]);   {        3 }

   5:  if Time[2] < 90 then Inc(Time[2]);   {        4 }

   6:  if Time[3] > 0  then Dec(Time[3]);   {        5 }

   7:  if Time[3] < 90 then Inc(Time[3]);   {        6 }

   8:  if Time[4] > 0  then Dec(Time[4]);   {        7 }

   9:  if Time[4] < 90 then Inc(Time[4]);   {        8 }

   59: ChangeStatus(1); { нажата F1 }

   60: ChangeStatus(2); {        F2 }

   61: ChangeStatus(3); {        F3 }

   62: ChangeStatus(4); {        F4 }

   63: ChangeStatus(5); {        F5 }

   64: ChangeStatus(6); {        F6 }

 end;

 Print('      ', 69, 11, White);

 Print('      ', 69, 12, White);

 Print('      ', 69, 13, White);

 Print('      ', 69, 14, White);

 Str(Time[1], Local_Time);

 Print(' + ' + Local_Time, 69, 11, White);

 Str(Time[2], Local_Time);

 Print(' + ' + Local_Time, 69, 12, White);

 Str(Time[3], Local_Time);

 Print(' + ' + Local_Time, 69, 13, White);

 Str(Time[4], Local_Time);

 Print(' + ' + Local_Time, 69, 14, White);

 Inline($9C);

 OldKHandler;

end;

{$F-}

{ Изменение размера курсора }

procedure SetCurSize(const BegLine, EndLine: Byte);

var

 Regs: Registers;

begin

 with Regs do begin

   AH := $01;

   CH := BegLine;

   CL := EndLine;

 end;

 Intr($10, Regs);

end;

{ Инициализация основных переменных }

procedure Initialize;

var

 i, j: Integer;

begin

 T1 := 0;

 T2 := 0;

 Top1 := 0;

 Top2 := 0;

 SetCurSize($20, $00);

 for i := 1 to 6 do

   Thread[i] := Active;

 for i := 1 to 4 do

   Time[i] := 0;

 PrintStatus(1);

 PrintStatus(2);

 Print('Не запущен', 66, 6, LightGray);

 Print('Не запущен', 66, 7, LightGray);

 Print('Не запущен', 66, 8, LightGray);

 Print('Не запущен', 66, 9, LightGray);

 Print('0.00 %', 66, 16, White);

 Print('0.00 %', 66, 17, White);

 Print('    + 0', 66, 11, White);

 Print('    + 0', 66, 12, White);

 Print('    + 0', 66, 13, White);

 Print('    + 0', 66, 14, White);

 X1 := 0;

 Y1 := 0;

 X2 := 0;

 Y2 := 0;

 Num := 1;

 dx := -1;

 dy := 1;

 SX := 50;

 SY := 3;

 for i := 0 to 1 do

   for j := 0 to 1 do begin

     tmp_attr[j, i] := Scr[SY + j, SX + i].Attr;

     tmp_symbol[j, i] := Scr[SY + j, SX + i].Symbol;

   end;

 GetIntVec($9, @OldKHandler);

 SetIntVec($9, Addr(KHandler));

 GetIntVec($8, @OldTHandler);

 SetIntVec($8, Addr(THandler));

end;

{ Действия при завершении работы программы }

procedure KillProc;

begin

 Thread[3] := Suspended;

 Thread[4] := Active;

 Thread[5] := Suspended;

 Thread[6] := Active;

 T := High(T);

 CurThread := 1;

 while (Top1 <> 0) or (Top2 <> 0) do begin

   T := 0;

   case Random(2) of

     0: Cons1(1 + Random(10));

     1: Cons2(1 + Random(10));

   end;

 end;

 SetIntVec($9, Addr(OldKHandler));

 SetIntVec($8, Addr(OldTHandler));

 Window(1, 1, 80, 25);

 GotoXY(1, 25);

 SetCurSize($06, $07);

 Halt(0);

end;

var

 v: String;

begin

 v := ParamStr(1);

 if (ParamCount = 0) or not ((Upcase(v[1]) = 'A') or (Upcase(v[1]) = 'B')) then begin

   WriteLn('Неправильно задано положение заголовка.');

   WriteLn('Формат:');

   WriteLn('имя_файла Pos');

   WriteLn('где Pos - положение заголовка (a - вверху, b - внизу).');

   ReadLn;

   Halt;

 end;

 if Upcase(v[1]) = 'B' then TPos := 25;

 TextBackground(Black);

 ClrScr;

 Window(2, 2, 42, 24);

 TextBackground(White);

 ClrScr;

 TextColor(Black);

 GotoXY(17, 1);

 Write('Процесс 1');

 Window(3, 3, 41, 23);

 TextBackground(Black);

 ClrScr;

 Window(2, 12, 42, 12);

 TextBackground(White);

 ClrScr;

 TextColor(Black);

 GotoXY(17, 1);

 Write('Процесс 2');

 Window(44, 2, 79, 24);

 TextBackground(White);

 ClrScr;

 GotoXY(14, 1);

 Write('Управление');

 Window(45, 3, 78, 23);

 TextBackground(Black);

 ClrScr;

 Window(45, 3, 78, 3);

 TextBackground(3);

 ClrScr;

 TextColor(White);

 GotoXY(8, 1);

 Write('Изменение состояний');

 Window(45, 4, 78, 9);

 TextBackground(Black);

 ClrScr;

 TextColor(White);

 WriteLn('F1 Заголовок       :');

 WriteLn('F2 Летающий квадрат:');

 WriteLn('F3 Производитель 1 :');

 WriteLn('F4 Потребитель   1 :');

 WriteLn('F5 Производитель 2 :');

 Write('F6 Потребитель   2 :');

 Window(45, 10, 78, 10);

 TextBackground(3);

 ClrScr;

 GotoXY(4, 1);

 Write('Время  <уменьшить>/<добавить>');

 Window(45, 11, 78, 14);

 TextBackground(Black);

 ClrScr;

 WriteLn('1/2 Производитель 1:');

 WriteLn('3/4 Потребитель   1:');

 WriteLn('5/6 Производитель 2:');

 Write('7/8 Потребитель   2:');

 Window(45, 15, 78, 15);

 TextBackground(3);

 ClrScr;

 GotoXY(7, 1);

 Write('Статистические данные');

 Window(45, 16, 78, 17);

 TextBackground(Black);

 ClrScr;

 WriteLn('Буфер 1 заполнен на:');

 Write('Буфер 2 заполнен на:');

 Window(45, 18, 78, 18);

 TextBackground(3);

 ClrScr;

 Window(45, 19, 78, 23);

 TextBackground(Black);

 ClrScr;

 GotoXY(1, 5);

 Write('Esc - выход');

 Initialize;

 Randomize;

 while True do begin

   if Kill then KillProc;

   CurThread := Random(4);

   case CurThread of

     0: Prod1(10 + Random(10));

     1: Cons1(10 + Random(10));

     2: Prod2(10 + Random(10));

     3: Cons2(10 + Random(10));

   end;

 end;

end.


 

А также другие работы, которые могут Вас заинтересовать

83741. Образование множественного числа имён существительных в английском языке 46.91 KB
  Цели урока: Ознакомление учащихся с образованием множественного числа существительных. Активизация лексики по теме House в диалогической речи. Формирование и развитие навыков чтения и аудирования. Развитие интереса к изучению английского языка.
83742. Россия и Германия в сравнении 120 KB
  Практические: активизировать лексику по теме; совершенствовать навыки чтения, говорения; развивать умения систематизировать, обобщать полученную информацию; Образовательные: расширять страноведческий кругозор; знания по профессии...
83743. В поисках счастья (Литературная экспедиция по сказкам А.С. Пушкина) 45.5 KB
  Цели образовательные: Учить внимательно читать произведения художественной литературы; формировать умения и навыки работы с текстом; осознавать свои чувства и эмоции при чтении сказок Пушкина; понять авторское отношение к сказочным героям и свое отношение к пушкинским героям.
83744. Односоставные предложения в произведении А.С.Пушкина «Капитанская дочка» 60.48 KB
  Честь нельзя отнять её можно лишь потерять Как вы понимаете его Какое слово является ключевым Как вы понимаете значение этого слова Давайте обратимся к электронным словарям и узнаем лексическое значение слова подберём синонимы и антонимы.
83745. Молекулярная физика и термодинамика 1.11 MB
  Задачи: закрепить основные понятия и закономерности темы умение выстраивать логические цепочки из основных законов; обобщить и систематизировать знания учащихся по основным вопросам термодинамики и молекулярной физики; закрепить умение решать графические задачи по изопроцессам I закону термодинамики...
83746. За сохранение и чистоту английского языка 143 KB
  Английский язык является языком международного общения. В России английский язык завоевывает все большую популярность и по своей значимости становиться вторым языком общения после родного. Россия – огромная страна и во всех уголках ее изучают английский язык.
83747. Возможности динамических (электронных) таблиц 460 KB
  Формы организации познавательной деятельности: групповая индивидуальная Средства обучения: презентация ПК с программным обеспечением и подключенным ЖК – телевизором для объяснения материала раздаточный материал для выполнения практического задания.
83748. Animals in our life 37.5 KB
  Учитель предлагает вспомнить стихотворение Моя мечта которое учащиеся учили дома наизусть. Сначала учитель прочитывает стихотворение затем по одной строчке вместе с детьми после чего каждый учащийся читает по одной строчки стихотворения по цепочке.
83749. Военная реформа Петра I 73.5 KB
  Цели урока: Дать характеристику военной реформы Петра I; Выяснить результаты петровской реформа; Значение петровской реформы для российской армии и России. Тема урока: объяснение нового материала. Методы и приёмы: Эвристическая беседа.