如何使用Go创建工作池? 配合计时器使用工作池 图文讲解 [_]~( ̄▽ ̄)~* Go相关

2023-05-16

文章目录

  • 使用go程通信创建工作池
  • 计时器(`time.Timer`)
  • 工作池与计时器

使用go程通信创建工作池

创建工作池会用到我上述的大部分特性
在这里插入图片描述

func 工作函数(id int, 任务 <-chan int, 结果 chan<- int) {
	for i := range 任务 {
		fmt.Printf("工作池:%d ++++++++ 任务:%d\n", id, i)
		time.Sleep(time.Second)
		fmt.Printf("工作池:%d -------- 任务:%d\n", id, i)
		结果 <- i * 2
	}
}

func main() {
	// 工作池
	任务 := make(chan int, 100)
	工作结果 := make(chan int, 100)
	// 创建工作池,开启5个go程
	for 工作池 := 1; 工作池 <= 5; 工作池++ {
		go 工作函数(工作池, 任务, 工作结果)
	}
	// 创建与分配任务
	for 创建任务 := 1; 创建任务 <= 5; 创建任务++ {
		任务 <- 创建任务
	}
	// 输出结果
	for 结果 := 1; 结果 <= 5; 结果++ {
		fmt.Println("工作结果:", <-工作结果)
	}
}

在这里插入图片描述
这里工作池和任务的数量都是可以更加需求动态改变的, 可以更加CPU的线程数创建对应数量的工作池(runtime.NumCPU返回当前CPU的线程数)

计时器(time.Timer)

网上已经有很多计时器相关的文章了, 如果你对计时器还不了解, 可以看一下这个大佬的文章一起学Go之计时器(Timer/Tick), 用计时器的时候需要注意内存泄漏。
简单说: go计时器分为两种, 一种执行一次就结束的常规计时器(time.Timer), 一种是按照计时一直会不断重复执行的循环计时器(time.Ticker)。
其中time.Timer创建计时器的方法主要有两种

  1. time.NewTimer(时间): 计时结束后会像内部的变量C(是一个时间类型管道)返回当前时间
  2. time.AfterFunc(时间, 函数()) 计时结束后会执行函数()
    常规的计时器, 可以重计(计时器.Reset(时间))或者关闭计时器(计时器. Stop())
    而另一种循环计时器(time.Ticker)是无法进行重计的, 只能进行关闭操作。
var 计时管道 = make(chan int, 5)

func 倒计时(时间 chan int) {
	i := <-时间
	time.Sleep(time.Second)
	时间 <- i + 1
}

func main() {
	计时器 := time.NewTimer(time.Second * 5)
	计时管道 <- 0
	for {
		go 倒计时(计时管道)
		select {
		case 结束时间 := <-计时器.C:
			fmt.Println("结束了, ", 结束时间)
			goto 结束
		case 当前时间 := <-计时管道:
			计时管道 <- 当前时间
			fmt.Println(当前时间)
		}
	}
结束:
}

计时器主要使用的场景之一就是超时关闭, 而且往往会配合 select - case进行使用, 下面我就用工作池配合计时器来完善工作池的机制。

工作池与计时器

上述工作池还有一个很不完善的地方, 上述程序想要正常工作, 我们需要事先知道其创建了多个任务, 来决定输出结果的数量, 但实际环境中, 这样的理想条件一般不会出现, 而更加长间的是利用超时机制, 等待一段时间后来彻底结束, Go的标准库中自带的计时器即可完成此功能。

func 工作函数(id int, 任务 <-chan int, 结果 chan<- int) {
	for i := range 任务 {
		fmt.Printf("工作池:%d ++++++++ 任务:%d\n", id, i)
		time.Sleep(time.Second)
		fmt.Printf("工作池:%d -------- 任务:%d\n", id, i)
		结果 <- i * 2
	}
}

func main() {
	// 工作池
	任务 := make(chan int, 100)
	工作结果 := make(chan int, 100)
	// 创建工作池,开启5个go程
	for 工作池 := 1; 工作池 <= 3; 工作池++ {
		go 工作函数(工作池, 任务, 工作结果)
	}
	// 创建与分配任务
	for 创建任务 := 1; 创建任务 <= 5; 创建任务++ {
		任务 <- 创建任务
	}
	// 创建计时器, 设置超时时间
	计时器 := time.NewTimer(10 * time.Second)
	defer 计时器.Stop()
	for i := 0; i < 1; {
		select {
		case 结果 := <-工作结果:
			计时器.Reset(10 * time.Second)
			fmt.Printf("当前Go程数量: %v, 工作结果: %v \n", runtime.NumGoroutine(), 结果)
		case <-计时器.C:
			i += 1
			// 这里把不用的管道销毁一下, 减少Go程数量, 同时也能避免内存泄漏
			close(工作结果)
			close(任务)
			// 等待go的垃圾回收机制来回收一下没用的Go程
			time.Sleep(time.Second)
			fmt.Println("当前Go程数量:", runtime.NumGoroutine())
			break
		}
	}
}

在这里插入图片描述

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

如何使用Go创建工作池? 配合计时器使用工作池 图文讲解 [_]~( ̄▽ ̄)~* Go相关 的相关文章

  • 【PX4代码】关于ekf2输出频率只有1ohz的问题

    问题 我在使用的是pixhawk 2代 imu的输出频率都在100hz以上 xff0c 使用的gps模块输出频率为5hz xff0c 使用log的local position csv 查看ekf2估计输出的点位信息只有10hz xff0c
  • Keil4中C51的debug调试步骤技巧

    1 选择相应的调试仿真连接器 xff1a 选择 xff1a project gt Options for Target 如下图所示 xff1a 然后在弹出对话框的Debug选项下选择仿真器的型号 xff1a 2 进入调试 xff1a 3 部
  • 怎么操作linux服务器

    Linux 服务器就是采用 Linux 系统的网络服务器 xff0c 同时也有采用 windows 的服务器 xff0c 作用是类似的 而 Linux 并不是一个特定的系统 xff0c 而是使用 Linux 内核的系统 xff0c 现在发行
  • 人工智能如何可以思考?

    近日在给同事讲人工智能的时候 xff0c 提到当数据量不够的时候 xff0c 必要时需要加入人工工程 xff0c 引导计算机 归纳 一些知识 xff0c 毕竟计算机智能比起人类智能 xff0c 最大的缺陷可能在于不懂得 举一反三 换句话说
  • bag文件内topic对应的frame_id查看指令

    启动ROS roscore 运行数据集 span class token comment 数据集小的话 xff0c 建议慢速播放 span rosbag play xxx span class token punctuation span
  • GPS数据类型(ROS)

    文章目录 一 传感器分类二 作用三 系统组成四 位置表示五 数据格式六 ROS中GPS数据格式sensor msgs NavSatFixROS中GPS数据主要包含这四类 xff0c 分别是gps 裸数据ros封装 xff0c 位置 xff0
  • cmake使用教程

    CMakeLists txt文档编写以及packsge xml文档介绍 CMakeLists txt文档一 cmake minimum required命令二 CMake中的编译类型三 cmake编译选项 xff08 与2对应 xff09
  • 四旋翼无人机飞控系统设计(闭环控制系统)

    对于一个简单的飞控程序来说 xff0c 控制器是它最核心的部分 xff0c 这里主要与大家讨论控制系统的基本理论知识 xff08 自控大佬请绕道 xff09 xff0c 包括控制系统概念 闭环控制系统的原理 下篇将侧重包含pid控制算法的具
  • 针对frame_id和child_frame_id的理解

    ros基础必看之各个frame的理解 ROS坐标系统 xff0c 常见的坐标系和其含义 ROS中TF 坐标系转换 原理与使用
  • IMU预积分学习

    IMU预积分学习 一 IMU状态传递方程 一 IMU状态传递方程 几种不同的表达形式 xff1a 1 lio mapping xff1a 参考大佬 xff1a lio mapping 及 VINS Mono代码及理论推导 xff08 2 x
  • Python3 内置模块 - os

    方法名说明os access判断文件权限os chdir改变当前工作目录os chmod file 修改文件权限os execvp 启动一个新进程os execvp 执行外部程序脚本 xff08 Uinx xff09 os fork 获取父
  • AttributeError: module 'tornado.web' has no attribute 'asynchronous'解决方法

    AttributeError module tornado web has no attribute 39 asynchronous 解决方法 今天看tornado异步时发现的错误 xff0c 查了一下 xff0c 原来tornado6以后
  • 【STM32项目】- 人体检测(体温、心率、心跳、跌倒检测)

    STM32人体检测 xff08 体温 心率 心跳 跌倒检测 xff09 43 zigbee 笔者前言 在闲鱼有缘结识的一个哥们 xff0c 帮助做的基于STM32人体检测系统 xff0c 我负责硬件程序开发设计 xff0c 哥们负责客户端服
  • ESP32 之 esp32-cam wifi拍照传图系统1

    文章目录 ESP32 之 esp32 cam wifi拍照传图系统1 效果演示2 材料准备3 原理图接线4 下载代码 ESP32 之 esp32 cam wifi拍照传图系统 1 效果演示 2 材料准备 ESP32 camUSB转TTL按钮
  • ESP32 之 esp32-cam wifi拍照传图系统2

    ESP32 之 esp32 cam wifi拍照传图系统 补充说明 ESP32 CAM总结 一 ESP32初识 ESP32 CAM模组的核心芯片 xff1a ESP32 S 模块是一款超小体积的多功能通用型 802 11b g n WiFi
  • 【PX4 飞控二次开发】第一个程序 打印输出-模拟

    第一个程序 1 编写任务代码 Cmake文件2 编译 1 编写任务代码 Cmake文件 span class token operator span span class token operator span PIX4 span clas
  • 【PX4 飞控二次开发】UORB 发布及订阅自定义

    UORB测试 一 添加msg1 创建 msg文件2 Cmakelists txt修改3 编译错误4 编译成功 二 发布及订阅主题1 添加代码2 修改cmake3 再次编译 一 添加msg 1 创建 msg文件 span class toke
  • 【PX4 飞控二次开发】自制ESP8266WIFI数传

    ESP8266数传模块 一 简介二 下载烧录固件1 下载MavLink ESP8266固件2 烧录 三 连线四 配置ESP8266五 连接WIFI Bridge 一 简介 ESP8266是一款低成本 xff0c 易于使用的Wi Fi模块 x
  • 四旋翼无人机飞控系统设计(PID控制算法)

    PID控制算法 PID控制器是一个结构简单并且成熟稳定的控制器 xff0c 在工业上应用广泛 包括比例 xff08 Proportion xff09 积分 xff08 Integral xff09 微分 xff08 Differential
  • 树莓派入门-环境搭建

    树莓派环境搭建 一 修改文件1 1系统安装1 2添加修改文件 二 更换源加速2 1修改sources list2 2修改raspi list2 3更新系统 三 配置系统3 1摄像头 VNC3 2安装TFTP服务3 3固定IP3 4分辨率修改

随机推荐