第一次尝试使用GO语言开启多线程调用结算存储过程。记录一下,以防忘记~
package main
import (
"database/sql"
"fmt"
"runtime"
"strconv"
_ "github.com/go-sql-driver/mysql"
)
// 创建一个channel
var complete chan int = make(chan int, 1)
var doState int = 0
func main() {
var errMsg string
var processNum, distribState int = 1, 0
fmt.Println("start")
db, err := sql.Open("mysql", "root:@127.0.0.1/test?charset=utf8")
if err != nil {
errMsg = "sql.Open:" + err.Error()
} else {
row := db.QueryRow("select ifnull(processNum,0),ifnull(distribState,0) from tb_calpara limit 1")
err := row.Scan(&processNum, &distribState)
if err != nil {
if err == sql.ErrNoRows {
errMsg = "未设置系统参数!"
} else {
errMsg = "row.Scan:" + err.Error()
}
} else {
//未开始分配
if distribState == 0 {
runtime.GOMAXPROCS(processNum)
var minQuotaID, maxQuotaID, beforeMax int
ssql := ` select min(quotaID) , max(quotaID) from tb_quota
where dataState in (2,3)
and ((lastPassDate is null and DATE_FORMAT(quotaDate,'%Y-%m-%d')<DATE_FORMAT(NOW(),'%Y-%m-%d'))
or (lastPassDate is not null and DATE_FORMAT(lastPassDate,'%Y-%m-%d')<DATE_FORMAT(NOW(),'%Y-%m-%d')))`
row := db.QueryRow(ssql)
err := row.Scan(&minQuotaID, &maxQuotaID)
if err != nil {
fmt.Println("111", err.Error())
} else {
if minQuotaID > 0 && maxQuotaID > 0 && processNum > 0 {
//求一个平均数
avg := (maxQuotaID - minQuotaID) / processNum
for i := 1; i <= processNum; i++ {
var min, max int
if i == 1 { //第一个
min = minQuotaID
max = min + avg
} else if i == processNum { //最后一个
min = beforeMax
max = maxQuotaID + 1
} else { //中间
min = beforeMax
max = min + avg
}
go autoDistrib(db, min, max, complete)
beforeMax = max
}
}
}
}
}
}
var value string
for j := 1; j <= processNum; j++ {
v := <-complete // 直到线程跑完, 取到消息. main在此阻塞住
value = value + strconv.Itoa(v) + ","
fmt.Println("channel:", value)
}
fmt.Println("channel的值为:", value)
var dstate int
row := db.QueryRow(`select ifnull(distribState,0) from tb_calpara limit 1`)
row.Scan(&dstate)
if dstate == processNum {
//修改参数表的分配状态
_, err := db.Exec(`update tb_calpara set distribState=ifnull(distribState,0)+1 limit 1;`)
if err != nil {
fmt.Println("444", err.Error())
}
}
fmt.Println("main函数运行结束...", errMsg)
defer db.Close()
}
//分配
func autoDistrib(db *sql.DB, min int, max int, ch chan int) {
fmt.Println("新线程运行开始...", min, max)
var isOk int = -1
var err string
//调用autoDistrib存储过程
_, xerr := db.Exec(`call proc_autoDistrib(
?, -- min ID
?, -- max ID
@isOK,
@err
);`, min, max)
if xerr != nil {
fmt.Println("distrib error: ", xerr)
} else {
row := db.QueryRow("select ifnull(@isOK,0), ifnull(@err,'');")
row.Scan(&isOk, &err)
if isOk < 0 {
fmt.Println("err:" + err)
}
}
doState = doState + 1
ch <- doState
fmt.Println(doState, min, max)
fmt.Println("新线程运行结束...")
}