可根据此思想进行多任务启动查询汇总数据。
原理
- 利用
job
机制开启后台进程。 - 利用
loop
循环减少进程的数量等于开启进程的数量,判断多进程任务是否完成。
- 创建表并插入
1000W
条数据,统计Moeny
字段总金额
- 创建
demo
代码如下。
Class Demo.SemaphoreDemo Extends %RegisteredObject
{
/// Do ##class(Demo.SemaphoreDemo).Sample(5)
ClassMethod Sample(pJobCount = 3)
{
k ^yx("Amt"),^yxAmt
/* 1.启动信号 */
s mSem = ##class(Demo.Sem).%New()
If ('($isobject(mSem)))
{
q "启动失败"
}
/* 2. 初始化信号量为0 */
d mSem.Init(0)
s t1 = $zh
/* 3. 按指定数量,启动后台任务 */
for i = 1 : 1 : pJobCount
{
j ..Task(i)
}
w "启动job时间:"_ ($zh - t1),!
/* 4. 等待后台任务完成 */
s tCount = i,tSC = 0
/* 后台任务完成的判断条件是:减少的信号量=总后台任务数 */
while (tSC < tCount)
{
s tSC = tSC mSem.Decrement(tCount, 10)
}
w "完成时间:"_ ($zh - t1),!
s moneyAmt = 0
s data = ""
for {
s data = $o(^yxAmt(data))
q:(data = "")
s moneyAmt = moneyAmt ^yxAmt(data)
}
d mSem.Delete()
w "总金额" _ moneyAmt,!
w "汇总时间:"_ ($zh - t1),!
q
}
ClassMethod Task(i)
{
s tSem = ##class(Demo.Sem).%New()
s moneyAmt = 0
for j = (i * 100000) 1 : 1 : (i 1) * 100000 {
s money = $li(^M.YxPersonD(j), 3)
s moneyAmt = moneyAmt money
}
s ^yxAmt("moneyAmt" _ i) = moneyAmt
s ^yx("Amt") = $i(^yx("Amt"))
d tSem.Open(##class(Demo.Sem).Name())
d tSem.Increment(1)
d tSem.%Close()
q moneyAmt
}
}
- 创建信号类,定义
name
和初始化信号方法。
Class Demo.Sem Extends %SYSTEM.Semaphore
{
ClassMethod Name() As %String
{
q "Semaphore"
}
Method Init(initvalue = 0) As %Status
{
try {
If (..Create(..Name(), initvalue)) {
ret 1
} else {
ret 0
}
} catch {
ret 0
}
}
}
- 调用
DHC-APP>Do ##class(Demo.SemaphoreDemo).Sample(5)
启动job时间:.098982
完成时间:.119744
总金额250088825096472
汇总时间:.119774