哲学家的行为简单地可以归结为:思索-->用餐-->继续思索。
于是可以把行为描述为:
type
TRhilosopher = class(TThread)
private
FTableware: array[0..1] of THandle;
FNameOrder: integer;
FDining: Boolean;
procedure ToPaintComport;
protected
procedure Execute;
override;
procedure Dining(Enter: Boolean);
virtual;
procedure Thinking;
virtual;
public
constructor Create(KitA, KitB: THandle;
NameOrder: integer);
end;
这是一个线程对象,创建的时候就已经明确了将要关心的筷子(KitA,KitB)和名字(NameOrder),
执行起来以后,这个线程对象将顺序完成思索和用餐工作:Tinking、Dining。详细协议如下:
constructor TRhilosopher.Create(KitA, KitB: THandle;
NameOrder: integer);
begin
FTableware[0] := KitA;
FTableware[1] := KitB;
FNameOrder := NameOrder;
FreeOnTerminate := True;
Randomize;
inherited Create(False);
end;
procedure TRhilosopher.Execute;
begin
while (not Terminated)do
begin
if WaitForMultipleObjects(2, @FTableware, True, INFINITE) = WAIT_OBJECT_0 then
begin
Dining(True);
// 进入用餐
Dining(False);
// 退出用餐
Thinking;
// 继续思索
end;
end;
end;
procedure TRhilosopher.Dining(Enter: Boolean);
begin
if Enter then
begin
FDining := True;
ToPaintComport;
Sleep(Random(500) + 100);
// 吃饭消耗时间
end
else
begin
FDining := False;
ToPaintComport;
Sleep(Random(1));
ReleaseSemaphore(FTableware[0], 1, nil);
ReleaseSemaphore(FTableware[1], 1, nil);
end;
end;
procedure TRhilosopher.Thinking;
begin
Sleep(Random(500)+3000);
// 思索消耗时间
end;
procedure TRhilosopher.ToPaintComport;
begin
// 非必需的,目的是在窗体上画出效果
case FNameOrder of
1: Form1.Draw1(FDining);
2: Form1.Draw2(FDining);
3: Form1.Draw3(FDining);
4: Form1.Draw4(FDining);
5: Form1.Draw5(FDining);
end;
end;
其中的 ToPaintComport 方法本身不是这个题目中必需的,在这里添加了这个方法,是因为我代码中有将哲学家线程对象中的行为画到窗体上的步骤(标准应该把这个方法放入Synchronize中,我省略了)。