StrDiffThread

{--------------------------------------------------------------}
{算法介绍:}
{题库系统按5000一组分组比较,5000道题内开启10个线程,分别从     }
{0,500,1000,1500,2000,2500,3000,3500,4000,4500位置开始与其后的所有试题比较}
{比较完成返回比较结果;等待所有5000已完成,然后循环5000的下一组,}
{比较完成返回第2组5000的比较结果                                }
{                                                               }
{--------------------------------------------------------------}

unit StrDiffThread;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, StdCtrls;

const
  C_threadCnt = 10; //开启线程个数
  C_groupCnt = 5000; //题数最小分组
  C_RetMaxCnt = 1000; //列表最多返回1000*10个值
  C_SPLITER = '-';

type
  TMyThread = class(TThread)
  protected
    procedure Execute; override;
  public
    iThreadId: Integer;
    bIsInUse: Boolean; //是否已启用
    bFinished: Boolean; //线程是否结束
    iTotalCount: integer; //试题总数
    iTotalItemList: TStringList; //试题字符串
    iRetList: TStringList; //返回比较结果字符串
    iCurrIndex: integer; //正在处理第几题;
    iCurrPercent:integer ;//当前处理试题的比例;
    iStart: integer; //起始位置
    iMaxValue: Double; // 0..1 之间的小数
    iGainCount: Integer; //本线程分配的试题个数(尾线程,题数不足5000)
  end;

function InitArrayFromItemBank(var itemList: TStringList; maxValue: Double): Boolean;
function GetAllThreadFinished(): Boolean;
function GetThreadPercent(index:Integer):integer;
function GetThreadRetList(index:Integer):TStringList;

var
  RunThread: array[0..C_threadCnt] of TMyThread; //运行线程实例对象

{----------------------implementation---------------------- ------}

implementation

uses CnStrDiff;

function InitArrayFromItemBank(var itemList: TStringList; maxValue: Double): Boolean;
var
  i, perCnt: integer;
begin
  Result := false;
  if (itemList = nil) or (itemList.Count = 0) then Exit;

   //组内试题个数;
  if itemList.Count < C_groupCnt then
    perCnt := Round(itemList.Count / C_threadCnt) //10个线程中每个线程分配的比对题个数5000/10=500
  else
    perCnt := Round(C_groupCnt / C_threadCnt);

  for i := 0 to C_threadCnt - 1 do
  begin
    if RunThread[i] <> nil then
    begin
      if not TMyThread(RunThread[i]).Terminated then
        TMyThread(RunThread[i]).Terminate; //需等待线程结束

      if TMyThread(RunThread[i]).iRetList <> nil then
        TMyThread(RunThread[i]).iRetList.Free; //释放临时变量

      TMyThread(RunThread[i]).Free;
      TMyThread(RunThread[i]) := nil;
    end;

    RunThread[i] := TMyThread.Create(true);
    RunThread[i].iThreadId := i;

    RunThread[i].bIsInUse := true;
    RunThread[i].iTotalItemList := itemList;
    RunThread[i].iTotalCount := itemList.Count; //题库总题量
    RunThread[i].iGainCount := perCnt; //分配题个数
    RunThread[i].iStart := i * perCnt; //从哪个题开始比对
    RunThread[i].iCurrIndex := i * perCnt; //正在比对第0题
    RunThread[i].iCurrPercent := 0;
    RunThread[i].bFinished := false;
    RunThread[i].iMaxValue := maxValue;
    RunThread[i].iRetList := TstringList.Create; //返回结果
    RunThread[i].Resume;
    Application.ProcessMessages;

  end;
  Result := true;
end;

function GetThreadPercent(index:Integer):integer;
begin
  Result := 0 ;
  if ( index >= 0) and ( index < C_threadCnt) and (RunThread[index] <> nil ) then
    Result := RunThread[index].iCurrPercent;
end;

function GetThreadRetList(index:Integer):TStringList;
begin
  Result := nil ;
  if ( index >= 0) and ( index < C_threadCnt) and (RunThread[index] <> nil ) then
    Result := RunThread[index].iRetList;
end;


procedure TMyThread.Execute;
var
  i, j: Integer;
  ret: Double;
  sourceStr, destStr, resStr, sourceId, destId: string;
begin
  FreeOnTerminate := false; {这可以让线程执行完毕后随即不释放}
  bFinished := false;
  iCurrPercent := 0 ;
 
  for i := iStart to iStart + iGainCount - 1 do
  begin
    sourceStr := iTotalItemList.Strings[i];

    //当前处理问题进度
    iCurrPercent := Round( 100*i/(iStart+iGainCount));

    //0-500与其后 1-5000比较
    for j := i + 1 to iTotalCount - 1 do
    begin
      destStr := iTotalItemList.strings[j];
       //比对字符串
      ret := SimilarText(sourceStr, destStr, True);

 

       //返回值列表不超限且比对结果超过设置比例
      if (iRetList <> nil) and (iRetList.Count < C_RetMaxCnt) and (ret >= iMaxValue) then
      begin
        resStr := FormatFloat('00.00%', ret * 100);
        sourceId := Copy(sourceStr, 0, Pos(C_SPLITER, sourceStr) - 1);
        destId := Copy(destStr, 0, Pos(C_SPLITER, destStr) - 1);
        iRetList.Add(sourceId + C_SPLITER + destId + C_SPLITER + resStr);
      end;
    end;
  end;
  iCurrPercent := 100;
  bFinished := true;
end;

function GetAllThreadFinished(): Boolean;
var
  i: integer;
begin
  Result := true;
  for i := 0 to C_threadCnt - 1 do
    if not RunThread[i].bFinished then
    begin
      Result := false;
      Break;
    end;
end;


end.

 

 

 

 

unit Unit2;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, RzPrgres, StdCtrls, Buttons, ComCtrls;

 


type
  TForm2 = class(TForm)
    BitBtn1: TBitBtn;
    RzProgressBar1: TRzProgressBar;
    Label1: TLabel;
    Label2: TLabel;
    RzProgressBar2: TRzProgressBar;
    Label3: TLabel;
    RzProgressBar3: TRzProgressBar;
    Label4: TLabel;
    RzProgressBar4: TRzProgressBar;
    Label5: TLabel;
    RzProgressBar5: TRzProgressBar;
    RzProgressBar6: TRzProgressBar;
    Label6: TLabel;
    Label7: TLabel;
    RzProgressBar7: TRzProgressBar;
    Label8: TLabel;
    RzProgressBar8: TRzProgressBar;
    Label9: TLabel;
    RzProgressBar9: TRzProgressBar;
    Label10: TLabel;
    RzProgressBar10: TRzProgressBar;
    Label11: TLabel;
    Edit1: TEdit;
    lv_result: TListView;
    procedure BitBtn1Click(Sender: TObject);
  private
    { Private declarations }
    function GetItemDBList(index: integer; var dbList: TStringList): Boolean;
  public
    { Public declarations }
    itemgroupList: TStringList;

  end;

var
  Form2: TForm2;

implementation

uses StrDiffThread;

{$R *.dfm}

function TForm2.GetItemDBList(index: integer; var dbList: TStringList): Boolean;
var
  i: Integer;
begin
  Result := false;
  //获取第index组试题,每组获取C_groupCnt个试题;

  for i := 0 to C_groupCnt - 1 do
  begin
    if dbList <> nil then
      dbList.Add(IntToStr(i + index * C_groupCnt) + '-' + FormatdateTime('yyyy-mm-dd HH:MM:SS', Now));
  end;
end;

procedure TForm2.BitBtn1Click(Sender: TObject);
var
  i, k, l, iGroupCnt, totalcnt: Integer;
  similar: Double;
  itemretList: TStringList;
  listitem: TListItem;
begin
  totalCnt := 6000; //总题数
  similar := StrToFloat(Edit1.text);

    //题库按一组groupCnt个题分若干组
  if totalCnt mod C_groupCnt = 0 then
    iGroupCnt := totalCnt div C_groupCnt
  else
    iGroupCnt := totalCnt div C_groupCnt + 1;

   //按组循环
  for i := 0 to iGroupCnt - 1 do
  begin
    if itemgroupList <> nil then
      itemgroupList.Free;
    itemgroupList := TStringList.Create;

 

    //读取试题存入itemgroupList
    GetItemDBList(i, itemgroupList);

    if InitArrayFromItemBank(itemgroupList, similar) then
    begin
       //等待所有线程结束
      while not GetAllThreadFinished() do
      begin
        for k := 0 to C_threadCnt - 1 do
        begin
          TRzProgressBar(self.FindComponent('RzProgressBar' + inttostr(k + 1))).Percent := GetThreadPercent(k);
        end;
        Application.ProcessMessages;
        Sleep(3000);
      end;

      for k := 0 to C_threadCnt - 1 do
      begin
        itemretList := GetThreadRetList(k);
        if (itemretList <> nil) and (itemretList.count > 0) then
        begin
          for l := 0 to itemretList.count - 1 do
          begin
            listitem := lv_result.Items.Add;
            listitem.Caption := IntToStr(l);
            listitem.SubItems.Add(inttostr(k + 1));
            listitem.SubItems.Add(itemretList.strings[l]);
          end;
        end;
      end;


    end;

    ShowMessage('处理完第'+inttostr(i)+'组');
  end;


end;

 

 

 

end.

 

111StrDiffThread_第1张图片

 

 

 

你可能感兴趣的:(Delphi)