信号(四)- 多进程任务示例

2022-08-03 10:14:16 浏览数 (2)

可根据此思想进行多任务启动查询汇总数据。

原理

  • 利用job机制开启后台进程。
  • 利用loop循环减少进程的数量等于开启进程的数量,判断多进程任务是否完成。
  1. 创建表并插入1000W条数据,统计Moeny字段总金额

  1. 创建demo代码如下。
代码语言:javascript复制
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
}
}
  1. 创建信号类,定义name和初始化信号方法。
代码语言:javascript复制
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
    }
}

}
  1. 调用
代码语言:javascript复制
DHC-APP>Do ##class(Demo.SemaphoreDemo).Sample(5)
启动job时间:.098982
完成时间:.119744
总金额250088825096472
汇总时间:.119774

0 人点赞