这么多种线程怎么协调工作呢,Semaphore WaitFor等好像都用不上。重谢。(100分)

  • 主题发起人 tianzhen
  • 开始时间
T

tianzhen

Unregistered / Unconfirmed
GUEST, unregistred user!
程序流程:
1,开5线程t1,取一级页面;(存到list1)
2,开10线程t2,取二级页面;(取list1,存到list2)
3,开50线程t3,处理二级页面。(取list2)
其中,list1,2起缓存作用并过滤重复项。
请问3种线程之间如何协调工作比较好呢?
btw,现在采用 while list.count>1000do
sleep(5000)的方式,很占资源。延长sleep则不能实时关闭应用程序。
 
同步的方法有很多中,最直接的就是"临界区":依次只能由一个线程来执行的一段代码,另一个线程在第一个线程处理完之前是不会被执行的.
在使用临界区之前必须要初始化:InitializeCriticalSection
网上这样的成熟代码很多,你搜索一下吧.
其实你这样的情况还不如这样,你建立一个变量,一旦满足才能开启另外一个线程,岂不是比什么while list.count>1000do
sleep(5000)要强一些
 
忘了说了:三种线程要同时运行的,程序是无限循环的。
 
while list.count>1000do
sleep(5000)
这句你是写在主线程里的吧?
你可以试着写一个线程的基类,三种线程都在基类上派生下来.
基类里写上一个过程WaitForTime()让线程每经过一次循环就等待几毫秒.等待可以用WaitForSingleObject(WaitForMultipleObjects)配合Event去控制.
在实际经验中得出一个结论如果某个线程陷入死循环.那么你的整个程序就会疯狂的抢占资源.如果在这个死循环中WaitFor一下就好多了.
 
while list.count>1000do
sleep(5000)是写在线程里的,比如
t2中写:while list2.count>1000do
sleep(5000)
t1中写:while list1.count>1000do
sleep(5000)
因为要根据list.count决定线程的进度,不然比如t1过快的话list1来不及被t2处理,
list1会无限增大,这个问题怎么通过WaitFor解决呢?
 
顶,重新总结问一下:
程序流程:
1,开5线程t1,取一级页面;(存到list1)
2,开10线程t2,取二级页面;(取list1,存到list2)
3,开50线程t3,处理二级页面。(取list2)
因为有无限多的1级页面要读取,所以任何时刻三种线程都要同时运行着,无限循环。
其中,list1,2起缓存作用并过滤重复项。
现在采用的协调方式如下:(很占资源,延长sleep则不能实时关闭应用程序。)
t1中写:while list1.count>1000do
sleep(5000)
t2中写:while list2.count>1000do
sleep(5000)

要根据2个list.count来协调3种线程,(不然比如t1过快的话list1来不及被t2处理,list1会无限增大)
请问用什么更好的思路呢,可惜不懂操作系统原理,脑袋都想炸了也没用。
 
formality说的WaitForTime 是指类似这样的东东吗?
procedure Delay(lMilliSeconds: Dword);
var
MyEvent :Thandle;
begin
MyEvent := CreateEvent(nil,True,False,nil) ;
waitforSingleObject(MyEvent,lMilliSeconds);
CloseHandle(MyEvent);
end;
 
是这样子的
每个线程中都要有一个CloseEvent:THandle(直接写在线程基类中)构造函数中带一个参数MyCloseEvent:THandle;执行构造函数时把这个THandel赋给CloseEvent.
主线程中也有一个CloseEvent:THandle,实例化线程类时把这个CloseEvent传递过去.
主线程在检测到WM_CLOSE消息时,SetEvent(CloseEvent);
线程等待用WaitForMultipleObjects(...)等待事件中必须包括CloseEvent,当检测到CloseEvent事件时退出线程.
这样能解决用Sleep(...)不能实时关闭应用程序的问题.但不能解决你的速度问题.
不清楚你的线程中到底是要处理什么不敢乱说.也许无法帮上什么忙.
 
1,先不说你的同步处理的怎么样,就你那上百个线程,你的程序就得慢得要死,你得程序线程得上下文切换就够你受得了。建议线程数量在10-20个之间。
2,象你这种问题队列增长是必然得,所以你使用判断队列得长度休眠得方式是可行的,但还应该设置不同类型线程的优先级,以达到尽可能少休眠线程的目的。
 
线程不算多啊,t1t2还没有充分利用网络带宽,50个t3,list2也一直不空。
因为用户对前台的要求是持续不断得看到t3的输出结果,
所以t3要从尽早开始执行(list1.count>1),过程中t3也不能停。
很头疼
 
你的线程还不多,可不是没有充分利用网络带宽吗,你的CPU大部分时间用在线程切换上了,哪有时间给你处理网络数据.
 
闭关2天,结果: 估计有走弯路,大侠们斧正。
主进程:
h_list1e,h_list1f: THandle;
//e=empty f=full
h_list2e,h_list2f: THandle;
...
CloseHandle(h_list1e);
CloseHandle(h_list1f);
CloseHandle(h_list2e);
CloseHandle(h_list2f);

t1.execute:
if list1.count>1 then
SetEvent(h_list1e);
if list1.count>1000 then
reSetEvent(h_list1f);
if WaitForSingleObject(h_list1f, INFINITE) <> WAIT_OBJECT_0 then
Application.ProcessMessages;
...
t2.execute:
if list2.count>1 then
SetEvent(h_list2e);
if list2.count>10000 then
reSetEvent(h_list2f);
if WaitForSingleObject(h_list2f, INFINITE) <> WAIT_OBJECT_0 then
Application.ProcessMessages;
if list1.count<1 then
begin
SetEvent(h_list1f);
reSetEvent(h_list1e);
end;
if WaitForSingleObject(h_list1e, INFINITE) <> WAIT_OBJECT_0 then
Application.ProcessMessages;
...

t3.execute:
if list2.count<1 then
begin
SetEvent(h_list2f);
reSetEvent(h_list2e);
end;
if WaitForSingleObject(h_list2e, INFINITE) <> WAIT_OBJECT_0 then
Application.ProcessMessages;
...
 
少了一部分:
主进程:
h_list1e := CreateEvent(nil, true, false, nil);
h_list2e:= CreateEvent(nil, true, false, nil);
h_list1f := CreateEvent(nil, true, true, nil);
h_list2f:= CreateEvent(nil, true, true, nil);
 
你似乎是我一个群里的,
这问题我有个非常完美的解决方案
 
我叫 遇神
 
少了一部分:
主进程: //这部分是不是也应该写成waitforsingle...方式?该怎么写?
t1.create(false);
repeat Application.ProcessMessages;
until listbox1.count>=1;
t2.create(false);
repeat Application.ProcessMessages;
until listbox2.count>=1;
t3.create(false);
 
睢志强 有什么完美方案 共享一下?
 
看了一下,说一下我的看法,错误之处还请大家指出来,也好让我一起学习.
1.子线程中用Application.ProcessMessages似乎没有意议,一般只有一个主线程的程序里防此假死现像才会用得比较多.
2.List1,2,3都存在多线程同时读写操作,是临界资源,且线程都属同一个进程,用临界区来控制将耗资源最低.
3.if list1.count>1 then
SetEvent(h_list1e);
类似这行代码,还没同步控制就直接访问了,万一正在执行List.Count>1这个比较语句时,还没有比较完,其它线程又对List1进行赋值呢?所以访List前先EnterCriticalSection(),访问完后LeaveCriticalSection()
4.t1,t2,t3用挂起与换醒方式来执行,以降低CPU占用,因为已经开了很多经程了.t1填数据后就判断list1.count,若list1.count大于一个数值时就唤醒t2,t2处理完了就挂起自已,这样t2就不用一直再判断list1.count是否已经达到了最小可处理量了.t2与t3之间也是类似这样, 可以提高效率.
5.t3开那么多线程,真的有这个必要吗?
 
t3我觉得还是用线程池更好,
 

Similar threads

S
回复
0
查看
3K
SUNSTONE的Delphi笔记
S
S
回复
0
查看
2K
SUNSTONE的Delphi笔记
S
D
回复
0
查看
1K
DelphiTeacher的专栏
D
I
回复
0
查看
423
import
I
顶部