为什么不会执行线程,还是执行?
我正在尝试为命令行接口做一个多线程随机数生成器,为此,我使用tthreads使用多个CPU内核来制作随机数。我的程序工作直到我试图启动一个线程,因为它似乎启动了,但据我所知,没有执行其代码,因为那时我的第196行循环应该结束,但事实并非如此。
{$mode objfpc}{$H+}
uses
{$IFDEF UNIX}
cthreads,
{$ENDIF}
Classes,
sysutils,
math;
type
TMyThread = class(TThread)
private
procedure ShowStatus;
protected
procedure Execute; override;
public
constructor Create(CreateSuspended: boolean);
end;
var
nums, temp1: int64;
f: tfilestream;
split_char: char;
commands: array[0..2] of int64;
writing: boolean = false;
done: array of boolean;
constructor TMyThread.Create(CreateSuspended: boolean);
begin
FreeOnTerminate := True;
inherited Create(CreateSuspended);
end;
procedure TMyThread.ShowStatus;
begin
done[temp1]:= false;
end;
procedure TMyThread.Execute;
var
s, temp: string;
i: uint64;
begin
Synchronize(@Showstatus);
i:= temp1;
s:= '';
while not nums < 0 do
begin
writeln('test.................................');
dec(nums);
temp:= inttostr(randomrange(commands[1], commands[2])) + split_char;
if high(s) + high(temp) > 4096 then
begin
if not writing then
begin
writing:= true;
f.Write(s[1], high(s));
s:= temp;
writing:= false;
end;
end
else
s:= s + temp;
end;
done[i]:= true;
end;
var
i, timestamp, timestamp2: uint64;
temp, cores: int64;
f_temp, temp_s: string;
close, time, written, writeable, file_specified, numbers_specified, range_specified, split_char_specified: boolean;
is_finished: boolean = false;
threads: array of TMyThread;
label
jump;
begin
timestamp:= gettickcount64;
time:= false;
writeable:= false;
written:= false;
file_specified:= false;
numbers_specified:= false;
range_specified:= false;
split_char_specified:= false;
cores:= 0;
for i:= 1 to paramcount() do
try
case paramstr(i) of
'/f', '/file': begin
file_specified:= true;
f_temp:= paramstr(i + 1).split('"')[0];
if fileexists(f_temp) then
deletefile(f_temp);
f:= tfilestream.create(f_temp, fmcreate);
writeable:= true;
end;
'/n', '/numbers': begin
numbers_specified:= true;
commands[0]:= strtoint(paramstr(i + 1)) - 1;
end;
'/r', '/range': begin
range_specified:= true;
commands[1]:= strtoint((paramstr(i + 1).split(';'))[0]);
commands[2]:= strtoint((paramstr(i + 1).split(';'))[1]) + 1;
end;
'/s', '/split', 'splitchar': begin
split_char_specified:= true;
split_char:=paramstr(i + 1)[1];
end;
'/t', '/time': time:= true;
'/tr', '/truerand': randomize;
'/c', '/cores': cores:= strtoint(paramstr(i + 1));
end;
except
if not writeable then
begin
write('cannot write to file');
written:= true;
end;
close:= true;
end;
if not file_specified then
begin
write('file not specified');
written:= true;
close:= true;
end;
if numbers_specified then
begin
if commands[0] < 1 then
begin
if written then
write(#13);
write('cannot generate <1 numbers');
written:= true;
close:= true;
end;
end
else
begin
if written then
write(#13);
write('amount of numbers not specified');
written:= true;
close:= true;
end;
if not range_specified then
begin
if written then
write(#13);
write('range not specified');
written:= true;
close:= true;
end
else
if commands[1] = commands[2] then
begin
temp:= commands[1];
commands[2]:= commands[1];
commands[2]:= temp;
end;
if not split_char_specified then
begin
if written then
write(#13);
write('split-char not specified');
close:= true;
end;
if close then
halt;
try
if (cores = 0) or (cores > getcpucount) then
cores:= getcpucount;
setlength(threads, cores);
setlength(done, cores);
for i:= low(threads) to high(threads) do
threads[i]:= default(Tmythread);
nums:= commands[0];
writeln(inttostr(length(threads)));
writeln('test0');
writeln('threadcount: ' + inttostr(length(threads)));
for i:= low(threads) to high(threads) do
begin
writeln('test?');
threads[i].create(true);
writeln('thread ' + inttostr(i) + ' initialized');
temp1:= i;
done[temp1]:= true;
while done[temp1] = true do
begin
writeln('waiting for thread to start');
end;
end;
writeln('test1');
while not is_finished do
begin
i:= 0;
jump:
if not done[i] then
goto jump;
inc(i);
if i = high(done) then
is_finished:= true;
end;
temp_s:= inttostr(randomrange(commands[1], commands[2])) + split_char;
f.Write(temp_s[1], high(temp_s));
except
on e: exception do
begin
write(#13 + e.message);
deletefile(paramstr(i));
write('ERROR! Program will exit');
exit;
end;
end;
f.free;
if time then
begin
if written then
write(#13);
write(floattostr((gettickcount64 - timestamp) / 1000) + ' seconds to execute');
end;
end.
I am trying to make a multithreaded random number generator for the command line interface, and for that I use TThreads to use multiple cpu cores to make random numbers. My program works till I try to start a thread, as it seemingly starts but, as far as I can tell, doesn't execute its code, because then my loop in line 196 should end, but it doesn't.
{$mode objfpc}{$H+}
uses
{$IFDEF UNIX}
cthreads,
{$ENDIF}
Classes,
sysutils,
math;
type
TMyThread = class(TThread)
private
procedure ShowStatus;
protected
procedure Execute; override;
public
constructor Create(CreateSuspended: boolean);
end;
var
nums, temp1: int64;
f: tfilestream;
split_char: char;
commands: array[0..2] of int64;
writing: boolean = false;
done: array of boolean;
constructor TMyThread.Create(CreateSuspended: boolean);
begin
FreeOnTerminate := True;
inherited Create(CreateSuspended);
end;
procedure TMyThread.ShowStatus;
begin
done[temp1]:= false;
end;
procedure TMyThread.Execute;
var
s, temp: string;
i: uint64;
begin
Synchronize(@Showstatus);
i:= temp1;
s:= '';
while not nums < 0 do
begin
writeln('test.................................');
dec(nums);
temp:= inttostr(randomrange(commands[1], commands[2])) + split_char;
if high(s) + high(temp) > 4096 then
begin
if not writing then
begin
writing:= true;
f.Write(s[1], high(s));
s:= temp;
writing:= false;
end;
end
else
s:= s + temp;
end;
done[i]:= true;
end;
var
i, timestamp, timestamp2: uint64;
temp, cores: int64;
f_temp, temp_s: string;
close, time, written, writeable, file_specified, numbers_specified, range_specified, split_char_specified: boolean;
is_finished: boolean = false;
threads: array of TMyThread;
label
jump;
begin
timestamp:= gettickcount64;
time:= false;
writeable:= false;
written:= false;
file_specified:= false;
numbers_specified:= false;
range_specified:= false;
split_char_specified:= false;
cores:= 0;
for i:= 1 to paramcount() do
try
case paramstr(i) of
'/f', '/file': begin
file_specified:= true;
f_temp:= paramstr(i + 1).split('"')[0];
if fileexists(f_temp) then
deletefile(f_temp);
f:= tfilestream.create(f_temp, fmcreate);
writeable:= true;
end;
'/n', '/numbers': begin
numbers_specified:= true;
commands[0]:= strtoint(paramstr(i + 1)) - 1;
end;
'/r', '/range': begin
range_specified:= true;
commands[1]:= strtoint((paramstr(i + 1).split(';'))[0]);
commands[2]:= strtoint((paramstr(i + 1).split(';'))[1]) + 1;
end;
'/s', '/split', 'splitchar': begin
split_char_specified:= true;
split_char:=paramstr(i + 1)[1];
end;
'/t', '/time': time:= true;
'/tr', '/truerand': randomize;
'/c', '/cores': cores:= strtoint(paramstr(i + 1));
end;
except
if not writeable then
begin
write('cannot write to file');
written:= true;
end;
close:= true;
end;
if not file_specified then
begin
write('file not specified');
written:= true;
close:= true;
end;
if numbers_specified then
begin
if commands[0] < 1 then
begin
if written then
write(#13);
write('cannot generate <1 numbers');
written:= true;
close:= true;
end;
end
else
begin
if written then
write(#13);
write('amount of numbers not specified');
written:= true;
close:= true;
end;
if not range_specified then
begin
if written then
write(#13);
write('range not specified');
written:= true;
close:= true;
end
else
if commands[1] = commands[2] then
begin
temp:= commands[1];
commands[2]:= commands[1];
commands[2]:= temp;
end;
if not split_char_specified then
begin
if written then
write(#13);
write('split-char not specified');
close:= true;
end;
if close then
halt;
try
if (cores = 0) or (cores > getcpucount) then
cores:= getcpucount;
setlength(threads, cores);
setlength(done, cores);
for i:= low(threads) to high(threads) do
threads[i]:= default(Tmythread);
nums:= commands[0];
writeln(inttostr(length(threads)));
writeln('test0');
writeln('threadcount: ' + inttostr(length(threads)));
for i:= low(threads) to high(threads) do
begin
writeln('test?');
threads[i].create(true);
writeln('thread ' + inttostr(i) + ' initialized');
temp1:= i;
done[temp1]:= true;
while done[temp1] = true do
begin
writeln('waiting for thread to start');
end;
end;
writeln('test1');
while not is_finished do
begin
i:= 0;
jump:
if not done[i] then
goto jump;
inc(i);
if i = high(done) then
is_finished:= true;
end;
temp_s:= inttostr(randomrange(commands[1], commands[2])) + split_char;
f.Write(temp_s[1], high(temp_s));
except
on e: exception do
begin
write(#13 + e.message);
deletefile(paramstr(i));
write('ERROR! Program will exit');
exit;
end;
end;
f.free;
if time then
begin
if written then
write(#13);
write(floattostr((gettickcount64 - timestamp) / 1000) + ' seconds to execute');
end;
end.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
线程有很多问题:
线程[i] .greate(true);
是创建线程对象的错误方法。您需要使用线程[i]:= tmythread.create(true);
而不是。您正在使用
createSuspended = true
创建每个线程,但是您在任何线程上不调用start> start()
恢复它们,以便它们实际运行。 /p>您的
execute()
方法正在调用synchronize()
作为其非常第一语句。但是您的项目是一个没有消息循环的控制台应用程序,该应用程序 请求,因此所有线程都会立即死锁。至少,您的主线程需要调用class.checksynchronize()
在工作线程运行时定期。您的线程正在共享和修改全局变量,而它们之间没有任何同步。任何不需要在全球共享的变量(例如每个线程的数组索引),都应传递到线程的构造函数并存储在类成员中。
您正在等待线程完成运行的方式既不正确又效率低下。
There are a number of problems with your threads:
threads[i].create(true);
is the wrong way to create the thread objects. You need to usethreads[i] := TMyThread.Create(true);
instead.you are creating each thread with
CreateSuspended=True
, but you don't callStart()
on any of the threads to resume them so they actually run.your
Execute()
method is callingSynchronize()
as its very 1st statement. But your project is a console app without a message loop that processesSynchronize()
requests, so all of your threads will deadlock immediately. At the very least, your main thread needs to callClasses.CheckSynchronize()
periodically while the worker threads are running.your threads are sharing and modifying global variables without any synchronization between them. Any variables that don't need to be shared globally (like each thread's array index) should be passed to the thread's constructor and stored in class members instead.
the way you are waiting for the threads to finish running is both incorrect and inefficient.