go 多线程处理高并发数据

// 推送绩效考核评价消息
func sendPerformanceMsg() {
	// 测试环境不执行
	if runEnvironment == 20 {
		return
	}
	defer func() {
		if err := recover(); err != nil {
			sbjlog.ExcLog("60", "sendPerformanceMsg Err:%v\n", err)
		}
	}()

	var err error
	sbjlog.Printf("Start 每天早上10点给未填写评价的用户推送评价提醒消息")
	var allPersonalAssessList []map[string]interface{} //待同步的数据
	var tempList *[]map[string]interface{}
	pageIndex, pageSize := 1, 100
	sqlWhere := " "

	for {
		tempList, err = sqlGetAllPagePersonalAssessList(pageIndex, pageSize, sqlWhere) //查询待评价的绩效考核数据
		if err != nil {
			return
		}

		allPersonalAssessList = append(allPersonalAssessList, *tempList...) //赋值
		if len(*tempList) < pageSize {                                      //查询得到的数据小于100条,说明是最后一页
			//跳出循环
			break
		}

		pageIndex++

	}
	allPersonalAssessListTotal := len(allPersonalAssessList)
	sbjlog.Printf("开始 每天早上10点 给未填写评价的用户推送评价提醒消息,一共要同步的数据是 %d 条 ", allPersonalAssessListTotal)
	// 获取当前时间戳
	tBegin := xtools.GetCurrentMillisecondInt64()
	// 计算读取耗时
	readUseTimeMs := xtools.GetUseTimeToMillisecondInt64(tBegin)
	// 计算线程数量 | 计划每个线程处理 20 个数据,最小 5 个线程,最大 15 个线程
	threadNum := CountDealThreadNum(allPersonalAssessListTotal, 20, 5, 15)

	// 打印日志
	sbjlog.Printf(" sendPerformanceMsg:需要推送  %d 个数据,计划开启 %d 个处理线程,读取耗时 %d ms", allPersonalAssessListTotal, threadNum, readUseTimeMs)

	// 检查读取耗时,如果超过 2 秒,推送 debug 给程序负责人、紧急联系人
	if readUseTimeMs > 2000 {
		sbjlog.SendDebug("sendPerformanceMsg,读取耗时: %d ms", readUseTimeMs)
	}
	// 获取当前时间戳
	tBegin = xtools.GetCurrentMillisecondInt64()

	//初始化一个处理结果通道
	resultChan := make(chan struct{}, threadNum)
	//当前处理的索引位置
	indexChan := make(chan int, 1)
	indexChan <- 0 //从第一条开始

	// 定时器 获取数据,放入通道
	for i := 0; i < threadNum; i++ {
		// 开启一个线程
		go func() {
			var index int //当前索引位置
			var tempData map[string]interface{}
			for {
				index = <-indexChan
				if index >= allPersonalAssessListTotal {
					indexChan <- index //通知其他异步结束
					return
				}
				tempData = allPersonalAssessList[index]
				index++
				//放回通道 给 下一条线程拿到当前索引
				indexChan <- (index)
				fmt.Println("处理数据",tempData)
				resultChan <- struct{}{} //写入处理结果
			}

		}()
	}
	// 收取处理结果
	for i := 0; i < allPersonalAssessListTotal; i++ {
		<-resultChan
	}
	// 打印日志
	sbjlog.Printf("sendPerformanceMsg,处理线程 %d 个,处理耗时 %d ms", threadNum, xtools.GetUseTimeToMillisecondInt64(tBegin))
	sbjlog.Printf("End 每天早上10点给未填写评价的用户推送评价提醒消息")
}

// 计算处理线程数量 | dataLen 数据长度, dealLen 单个线程处理长度, minLen 最小线程数, maxLen 最大线程数
func CountDealThreadNum(dataLen, dealLen, minLen, maxLen int) int {
	// 计划线程数
	planThreadNum := (dataLen + dealLen - 1) / dealLen
	// 判断是否在范围内
	switch {
	case planThreadNum > maxLen: // 计划 超出 最大长度限制
		// 返回最大线程数
		return maxLen
	case planThreadNum < minLen: // 计划 小于 最小长度限制
		if dataLen < minLen { // 数据长度 小于 最小长度限制
			// 返回数据长度
			return dataLen
		}
		// 返回最小线程数
		return minLen
	default:
		// 返回计划线程数
		return planThreadNum
	}
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值