多线程读同一个队列,ADO方式查询和修改同一个表,请问如何保证表和队列的安全。附源代码(200分)

  • 主题发起人 主题发起人 filter
  • 开始时间 开始时间
F

filter

Unregistered / Unconfirmed
GUEST, unregistred user!
初学多线程,我迷惑在以下几点:
1、我的队列类是自己写的,怎么加上队列锁,使多个线程读取一个队列不出问题,看了下tqueue,也不带队列锁
2、我是一个死循环读列队,判断队列是否有数据,有则读出,没有则继续循环,这样对系统消耗太大,CPU占用有100%了
3、线程在共同访问一个表时,需要用线程安全,资料上说应该加上Synchronize,晨同放一个datasource:=adoquery;datasource我没有用到,因为只需要ADOQUERY adoconnect就行了。这里线程安全是怎么做的。
type
TtestThread = class(TThread) //自定义线程
protected
qry: TADOQuery;
Ado: TADOConnection;
procedure Execute;
override;
procedure CreateConnectAdoProc;
//创建连接ADO
procedure OpenSqlProc;
//打开数据集
procedure ConnectDataSource;
end;

procedure TtestThread.CreateConnectAdoProc;
var
constr : string;
begin
Qry := TADOQuery.Create(nil);
Ado := TADOConnection.Create(nil);
Ado.ConnectionString := ado_oracle;
//连接ADO串
Ado.LoginPrompt:= false;
if not Ado.Connected then
Ado.Connected := True;
end;

procedure TtestThread.OpenSqlProc;
var
str:string;
begin
if Qry.Connection = nil then
Qry.Connection := Ado;
while truedo
//死循环,CPU占用太高
begin
WaitforsingleObject;
str:=kk.get();
if str<>'' then
begin
Qry.Close;
Qry.SQL.Clear;
Qry.SQL.Text := 'select * from ayjf';//strSql;
Qry.Prepared;
Qry.Open;
str:='';
end;
sleep(10);

end;
end;

procedure TtestThread.ConnectDataSource;
begin
//这里应该怎么写?
end;

procedure TtestThread.Execute;
var
strSql : string;
begin
inherited;
FreeOnTerminate := true;
CoInitialize(nil);
CreateConnectAdoProc;//创建连接ADO
strSql := 'select............';
//略
strsql:='update ....';
//略
OpenSqlProc;
//打开数据集
Synchronize(ConnectDataSource);
end;

procedure TfrmMain.Button2Click(Sender: TObject);
var
hThread:Thandle;
ThreadID:DWord;
i:integer;
begin
//想提高速度,所以用多个线程
for i:=0 to 10do
TtestThread.create(false);
end;

麻烦高手请改下代码,多谢!
 
我的队列类:
unit Queue;
interface
const max=2048;
type hb_record=record
tel:string;
outstr:string;
end;

type
Tqueue=class
private
{ Private declarations }
//队列专用
recivegroup:array [0..max-1] of string;
m_rear:integer;
m_head:integer;
messg:string;
public
constructor Create;
destructor Destory;
function isfull():boolean;
function getcount():integer;
function isempty():boolean;
function clear():boolean;
function put(m_sg:string):boolean;
function get():string;
function peek():string;
{ Public declarations }
end;

implementation
constructor Tqueue.Create;
begin

end;

destructor Tqueue.Destory;
begin
end;

//判断队列是否为满
function Tqueue.isfull():boolean;
begin
if (m_head=((m_rear+1) mod max))
then
result:=true
else
result:=false;
end;

//获得队列中消息数量
function Tqueue.getcount():integer;
begin
if (m_rear>=m_head)
then
result:=m_rear-m_head
else
result:=max+m_rear-m_head;
end;

//判断队列是否为空
function Tqueue.isempty():boolean;
begin
if (m_rear=m_head)
then
result:=true
else
result:=false;
end;

//清除队列
function Tqueue.clear():boolean;
begin
if m_rear=m_head
then
result:=true
else
result:=false;
end;

//放置消息到队列
function Tqueue.put(m_sg:string):boolean;
begin
if isfull
then
begin
result:=false;
exit;
end;
recivegroup[m_rear]:=m_sg;
m_rear:=(m_rear+1) mod max;
result:=true;
end;

//从队列中取出消息
function Tqueue.get():string;
begin
if isempty then
exit;
messg:=recivegroup[m_head];
m_head:=(m_head+1) mod max;
result:=messg;
end;

//获得当前要取出的队列消息
function Tqueue.peek():string;
begin
if isempty then
exit;
messg:=recivegroup[m_head];
result:=messg;
end;

end.
 
这个问题你问的太晚了,本来想好好答的,但是现在没时间了。马上回老家了。2点的火车,还要去接人。如果这个问题还在,年后我再来答。
现在我简单说一下:
一般情况,接收数据放在一个线程中,处理数据放在一个线程中
主要问题在这里
while truedo
//死循环,CPU占用太高
begin
WaitforsingleObject;
str:=kk.get();
if str<>'' then
begin
Qry.Close;
Qry.SQL.Clear;
Qry.SQL.Text := 'select * from ayjf';//strSql;
Qry.Prepared;
Qry.Open;
str:='';
end;
sleep(10);

end;

改为:
while truedo
//死循环,CPU占用太高
begin
if ( WaitForSingleObject( hEvent , INFINITE ) = WAIT_OBJECT_0 ) then
str:=kk.get();
if str<>'' then
begin
Qry.Close;
Qry.SQL.Clear;
Qry.SQL.Text := 'select * from ayjf';//strSql;
Qry.Prepared;
Qry.Open;
str:='';
end;
// sleep(10);
这句去掉
//数据处理结束后再打开信号
setevent(hevent);
end;

然后在你列队,有数据时,打开事件信号量,因为有多个线程在处理数据,所以你的列队也要同步,因为有可能数据还没有处理结束,新数据又到了。处理方法同上。
 
WaitForSingleObject( hEvent , INFINITE )
setevent(hevent);
能贴下具体的代码吗?
 
后退
顶部