1 註冊中心 1.1 為什麼要用註冊中心 微服務之間會相互調用,假如有兩個服務orderService和userService,orderService會調用userService獲取當前訂單相關的用戶信息,且userService部署了多個實例: 大家思考幾個問題: order-service在發 ...
mormot.core.threads--TSynParallelProcess
{ ************ 線程池中的並行執行 }
type
/// TSynParallelProcess 的並行化過程回調
// - 如果 0<=IndexStart<=IndexStop,則應執行某些過程
TOnSynParallelProcess = procedure(IndexStart, IndexStop: integer) of object;
/// 為 TSynParallelProcess 執行過程的線程
TSynParallelProcessThread = class(TSynBackgroundThreadMethodAbstract)
protected
fMethod: TOnSynParallelProcess; // 回調方法
fIndexStart, fIndexStop: integer; // 要處理的索引範圍
procedure Start(const Method: TOnSynParallelProcess; // 開始執行過程
IndexStart, IndexStop: integer);
/// 執行 fMethod(fIndexStart,fIndexStop)
procedure Process; override;
public
end;
/// 允許線上程池中並行執行基於索引的過程
// - 將創建自己的線程池,然後將工作分配給每個線程執行
TSynParallelProcess = class(TSynPersistentLock)
protected
fThreadName: RawUtf8; // 線程名稱
fPool: array of TSynParallelProcessThread; // 線程池
fThreadPoolCount: integer; // 線程池中的線程數
fParallelRunCount: integer; // 並行運行次數
public
/// 初始化線程池
// - 您可以定義一些回調來嵌套線程執行,例如,分配給 TRestServer.BeginCurrentThread/EndCurrentThread
// - 最多可設置 MaxThreadPoolCount=32 個線程(您可以允許更大的值,但此線程池的目的是使其進程飽和每個 CPU 核心)
// - 如果 ThreadPoolCount 為 0,則不會創建線程,並且過程將在當前線程中執行
constructor Create(ThreadPoolCount: integer; const ThreadName: RawUtf8;
const OnBeforeExecute: TOnNotifyThread = nil; // 執行前通知回調
const OnAfterExecute: TOnNotifyThread = nil; // 執行後通知回調
MaxThreadPoolCount: integer = 32); reintroduce; virtual;
/// 終結線程池
destructor Destroy; override;
/// 並行運行一個方法,並等待執行完成
// - 將 Method[0..MethodCount-1] 的執行分散到線程中
// - 如果在過程中發生任何異常,則此方法將引發 ESynParallel 異常
// - 如果設置了 OnMainThreadIdle,則當前線程(例如,預期為主 UI 線程)將不會處理任何內容,但在等待後臺線程時調用此事件
procedure ParallelRunAndWait(const Method: TOnSynParallelProcess;
MethodCount: integer; const OnMainThreadIdle: TNotifyEvent = nil);
published
/// 已激活的線程數
property ParallelRunCount: integer
read fParallelRunCount;
/// 此實例線程池中當前有多少線程
property ThreadPoolCount: integer
read fThreadPoolCount;
/// 一些文本標識符,用於區分每個擁有的線程
property ThreadName: RawUtf8
read fThreadName;
end;
後期再整理!
由於 TSynParallelProcess
在mORMot 2框架中是一個假定的類(因為標準的mORMot 2庫並不直接包含這個類名,但它可能是一個自定義擴展或類似功能的類的代表),我將基於您提供的類定義來編寫一個假設的常式代碼,這個代碼將模擬在Free Pascal中使用這樣一個類。
請註意,以下代碼將不會直接編譯,因為 TSynParallelProcess
和 TSynParallelProcessThread
的具體實現細節(如構造函數、析構函數和方法的內部邏輯)並未給出。但是,我將提供一個結構化的示例,展示如何使用這樣的類(如果它存在的話)。
program TSynParallelProcessDemo;
{$MODE DELPHI}
uses
SysUtils, Classes; // 引入必要的單元
// 假設TSynParallelProcess和TSynParallelProcessThread已經在某個單元中定義
// 這裡我們使用一個占位符單元名YourMormotUnit
// 註意:在實際應用中,您需要替換'YourMormotUnit'為包含這些類的實際單元名
uses YourMormotUnit;
procedure MyParallelTask(IndexStart, IndexStop: integer);
begin
// 這裡是您的並行任務邏輯
WriteLn('Executing task with indices from ', IndexStart, ' to ', IndexStop);
// 模擬耗時操作
Sleep(100); // 假設每個任務需要一些時間來完成
end;
var
ParallelProcessor: TSynParallelProcess;
TaskCount: Integer;
begin
try
// 初始化任務計數(這裡假設我們有100個任務要並行處理)
// 註意:在實際應用中,您可能需要根據具體情況來確定這個值
TaskCount := 100;
// 創建TSynParallelProcess實例
// 註意:這裡我們假設ThreadPoolCount是一個合理的值,例如CPU核心數的兩倍
// 並且MaxThreadPoolCount足夠大以容納所需的線程數
// ThreadName是可選的,用於標識線程池中的線程
ParallelProcessor := TSynParallelProcess.Create(
System.SysUtils.GetProcessorCount * 2, // 假設線程池大小為CPU核心數的兩倍
'MyParallelTasks', // 線程名稱首碼(可選)
nil, // OnBeforeExecute回調(這裡不使用)
nil // OnAfterExecute回調(這裡不使用)
);
try
// 並行運行任務並等待完成
// 註意:這裡的ParallelRunAndWait是假設的方法,它可能不直接存在於TSynParallelProcess中
// 您需要根據實際的方法簽名和邏輯來調整以下調用
// 由於我們沒有ParallelRunAndWait的具體實現,這裡只是一個示意性的調用
// 在實際中,您可能需要調用一個不同的方法,或者ParallelRunAndWait本身就需要您來實現
// 假設ParallelRunAndWait接受一個任務過程和任務總數作為參數
ParallelProcessor.ParallelRunAndWait(
@MyParallelTask, // 指向您的並行任務過程的指針
TaskCount // 要並行處理的任務總數
);
finally
// 銷毀TSynParallelProcess實例
ParallelProcessor.Free;
end;
except
on E: Exception do
WriteLn('An error occurred: ', E.Message);
end;
// 保持控制台視窗打開,直到用戶按任意鍵
WriteLn('Press Enter to exit...');
ReadLn;
end.
重要說明:
- 類和方法的存在性:上述代碼假設
TSynParallelProcess
類及其ParallelRunAndWait
方法存在。在mORMot 2的標準庫中,這樣的類和方法可能不存在,或者它們的名稱和參數可能有所不同。 - 實現細節:由於我們沒有
TSynParallelProcess
和TSynParallelProcessThread
的具體實現,因此上述代碼中的ParallelRunAndWait
調用是示意性的。在實際應用中,您需要根據實際可用的方法來實現並行任務的執行。 - 線程池大小:在創建
TSynParallelProcess
實例時,我使用了System.SysUtils.GetProcessorCount * 2
作為線程池的大小。這隻是一個常見的啟髮式方法,用於確定合理的線程數。然而,最佳線程數取決於您的具體應用程式和工作負載。 - 錯誤處理:代碼中包含了基本的錯誤處理邏輯,用於捕獲並列印異常消息。在實際應用中,您可能需要根據需要擴展這種錯誤處理。
- 單元引用:請將
uses YourMormotUnit;
中的YourMormotUnit
替換為包含TSynParallelProcess
和TSynParallelProcessThread
定義的實際單元名。如果這些類是您自定義的,那麼您需要確保它們已經被正確編譯並包含在您的項目中。