如果我想限制可以在词典中同时完成的线程查找的数量,该怎么做?并让线程睡眠,直到他们可以访问词典。即。如果两个查找已经在并行进行,则其他查找必须等待,直到LookupCount小于2才能执行。
TLexicon
MaxLookups: Integer;
LookupCount: Integer;
除了TLexicon之外,我创建了TLookupJob,它可以在TLookupThread中执行。 LookupJob.Execute过程调用词典上的查找并等待,直到有响应。
因此,LookupThreads必须睡眠,直到Lexicon.LookupCount小于Lexicon.MaxLookups。为此,我在LookupJob.Execute中调用GoSleep(事件),并且LookupThread的执行停止。但是如何以及何时发出信号。我不清楚设计的其余部分。
这里可以使用什么设计?
到目前为止,我已经创建了许多类:
TLexicon - 具有MaxLookups和LookupCount,以及查找功能。
LookupItem - 包含LookupWord和Response。传递给Lexicon.Lookup。
TLookupJob - 具有执行过程,以及GoSleep使用事件进行睡眠的WakeUp过程。
LookupThread - 执行LookupJob
随意更改设计。
答案 0 :(得分:5)
如果您的目标是Windows平台,WinAPI会提供合适的同步功能。请参阅CreateSemaphore,ReleaseSemaphore,WaitForSingleObject。 (当然,平台无关的选项可能是首选,但在某些环境中这可能仍然有用。)
创建/初始化词典时,请按如下方式创建一个sempaphore:
FSemaphoreHandle := CreateSemaphore(nil, MaxLookups, MaxLookups, nil);
然后在进行查找时,使用信号量来限制有多少线程同时进入查找例程的主体。
function TLexicon.Lookup(...): ...;
begin
//The wait function will block if the current counter = 0 and wait
//until another thread releases a counter.
WaitForSingleObject(FSemaphoreHandle, <timeout>);
//When the wait function returns (assuming due to semaphore count
//available and not timeout), the current counter of the semaphore
//is decreased. This mechanism limits the number of threads that
//can get past the wait funtion.
try
//Do lookup
finally
//By releasing the semaphore, the current counter is increased again,
//allowing a blocked thread to get past the wait function.
ReleaseSemaphore(FSemaphoreHandle, 1, nil);
end;
end;
最后,当你完成词典时,不要忘记CloseHandle。
注意:这是一个简单的例子。不要忘记添加适当的错误检查。例如。 WaitForSingleObject指示是否可以获取信号量。