我有以下情况:
我正在编写的程序模拟多个空中网络。现在我已经编写了它,以便每个模拟都有自己的线程和自己的数据。这样就不会有数据污染,每个线程都是完整的多任务处理安全。我为每个线程实现了delphi的本机TThread类。
该程序有一个主线程。然后它为每个网络创建多个子线程(我当前的测试用例有6个)。但是每个子线程还有4个额外的线程,因为它的网络有多个布局。总共我有31个线程,但只有24个线程正在积极处理。所有线程都以挂起模式创建,以便我可以手动启动它们。
我运行的计算机是一台i5笔记本电脑,因此它有4个线程(2个物理核心+ 2个HT)。在生产环境中,这将在服务器上运行,因此它们将具有更强的处理能力。
现在在主程序线程中,我在执行线程的for循环之后添加了一个断点。这不会立即触发。看着Delphi的调试控制台,看起来它一次只能主动运行4个线程。一旦退出,它就会启动另一个线程。
线程中的模拟很难优化,需要一些循环才能完成模拟。每个循环都需要前一个循环的数据。但每个模拟完全独立于下一个,因此该程序是螺纹和管道衬里的绝佳候选。
现在我的问题是为什么它只启动4个线程而不是代码指定的所有线程?
编辑添加了一些代码
主程序
for i := 0 to length(Solutions)-1 do
begin
Solutions[i].CreateWorkers; //Setup threads
end;
for i := 0 to length(Solutions)-1 do
begin
Solutions[i].Execute; //start threads
end;
end;
isSolversBusy := false; //breaking point doesn't trigger here
第1级线程
procedure cSolution.Execute;
var
i : integer;
lIsWorkerStillBusy : boolean;
begin
lIsWorkerStillBusy := true;
for i := 0 to length(Workers)-1 do
begin
Workers[i].Start;
end;
while (lIsWorkerStillBusy) do
begin
lIsWorkerStillBusy := false;
for i := 0 to length(Workers)-1 do
begin
if Workers[i].IsCalculated = false then
begin
lIsWorkerStillBusy := true;
end;
end;
sleep(100);
end;
FindBestNetwork;
IsAllWorkersDone := true;
end;
第二级线程
procedure cWorker.Execute;
begin
IsCalculated := false;
Network.UpdateFlows;
Network.SolveNetWork; //main simulation work
CalculateTotalPower;
IsCalculated := true;
end;
编辑2
我创建它们的原因全部被暂停是因为我将它们存储在一个数组中,在我启动它们之前,我首先创建了worker和它们的属性。我正在模拟空中网络场景。每个解决方案都是不同的布局,而每个工作者都是运行该布局的不同方式。
我必须首先计算所有工人的启动属性,然后再启动它们。在后面的视线中我可以修改代码来在线程中执行此操作。它目前发生在主线程中。线程的创建发生在我粘贴的代码片段之前。
我将它们全部保存在线程中的原因是我需要评估每个线程的结果。
答案 0 :(得分:14)
这是你的问题:
for i := 0 to length(Solutions)-1 do
begin
Solutions[i].Execute; //start threads
end;
不启动线程 - 这是在调用线程中执行Execute
方法。事实上,你一次只运行4个线程,你甚至没有运行一个 - 所有这些工作都将在主线程上顺序完成。要恢复暂停的主题,您必须使用Solutions[i].Start
。
Execute
的{{1}}方法是在TThread
自动创建的工作线程上执行的特殊方法。创建TThread
时,此方法会自动在TThread
创建的工作线程上运行。如果你创建了挂起的线程,那么它只是等待你在开始这项工作之前唤醒线程。调用TThread
的{{1}}方法就是实现这一点 - 触发底层工作线程开始执行.Start
方法。
否则,TThread
方法和.Execute
的所有其他方法与属于某个类的任何其他常规方法没有区别。它们可以在任何直接调用它们的线程上执行。
在这种情况下,在创建和执行工作线程之间的主线程中,您似乎没有做任何额外的工作。在这种情况下,除非您明确需要它,否则您可以简单地创建未挂起的线程,并让它们在创建时自动执行。