Go简单实现协程池的实现示例
作者:爪哇盘古 发布时间:2024-02-19 07:35:16
首先就是进程、线程、协程讲解老三样。
进程: 本质上是一个独立执行的程序,进程是操作系统进行资源分配和调度的基本概念,操作系统进行资源分配和调度的一个独立单位。
线程: 是操作系统能够进行运算调度的最小单位。它被包含在进程之中,是进程中的实际运作单位。一个进程中可以并发多个线程,每条线程执行不同的任务,切换受系统控制。
协程: 又称为微线程,是一种用户态的轻量级线程,协程不像线程和进程需要进行系统内核上的上下文切换,协程的上下文切换是由用户自己决定的,有自己的上下文,所以说是轻量级的线程,也称之为用户级别的线程就叫协程,一个线程可以多个协程,线程进程都是同步机制,而协程则是异步Java的原生语法中并没有实现协程,目前python、Lua和GO等语言支持。
关系:一个进程可以有多个线程,它允许计算机同时运行两个或多个程序。线程是进程的最小执行单位,CPU
的调度切换的是进程和线程,进程和线程多了之后调度会消耗大量的CPU,CPU上真正运行的是线程,线程可
以对应多个协程。
MPG模型
Go协程中有三个关键实体:
M(machine): 工作线程,由操作系统调度。应该就是通常所说的内核线程。
P(processor): 处理器(非CPU),代表着运行Go代码的必要资源,以及调度goroutine的能力。个人觉得可以当作拥有自主调度权的算法模块,用于工作窃取(work stealing)。
G(gooutine): Go协程,轻量级用户线程。主要包含执行栈和调度管理器。这里的调度管理器指的是,统一并管理调度资源,等待被调度。
Go协程的特点
(1)有独立的栈空间
(2)共享程序的堆空间
(3)协程调度由用户控制(进程的控制是有操作系统控制,程序员不能控制)
(4)协程是轻量级的线程
通道的特性
Go语言中的通道(channel)是一种特殊的类型。在任何时候,同时只能有一个 goroutine 访问通道进行发送和获取数据。goroutine 间通过通道就可以通信。
通道像一个传送带或者队列,总是遵循先入先出(First In First Out)的规则,保证收发数据的顺序。
当然协程的轻量性并不代表可以随意滥用,毕竟还是存在资源的消耗。本文主要讲解go的协程池的实现原理,利用select来监听任务。【代码仅用作实现原理,想更优雅可以在该原理基础上自行优化】
废话不多说直接上代码!
package main
import (
"strconv"
"time"
)
/**
协程池
*/
//全局任务管道地址数组
var arr []*chan func()
//启动任务数量
var num = 10
//默认管道下标0
var index = 0
//任务开关
var static = false
func run(f *chan func()){
println("等待咯")
for static == true {
select {
case fu:=<-*f : // 检测有没有数据可读
// 一旦成功读取到数据,则进行该case处理语句
fu()
default:
//println(f)
//println("无数据")
}
time.Sleep(time.Duration(1)*time.Second)
}
}
//启动任务函数
func Start(){
static = true
for i:=0;i<num;i++ {
//make一个管道地址
c:=make(chan func(),1)
println(&c)
//将该地址存入全局数组中
arr = append(arr,&c)
//地址传入任务函数
go run(&c)
}
}
//插入任务
func add(str string) {
//此处不是很优雅,自行优化实现。
if(index >= num-1){
index = 0
}else{
index++
}
//向地址管道传入函数
*arr[index] <- func() {
println(str)
}
}
//停止任务
func stop() {
//终止任务for
static = false
//清空管道数组
arr = []*chan func(){}
}
func main() {
Start()
println("开始执行写入管道")
println(len(arr))
for i:=0;i<1000000000;i++ {
add("传入的i:"+strconv.Itoa(i))
}
time.Sleep(time.Duration(2)*time.Second)
stop()
//time.Sleep(time.Duration(100)*time.Second)
}
原理很简单,就是合理使用select来监听管道是否有数据,协程池的实现就是合理利用管道。可以根据该思路来进行优化封装一个属于自己的协程池哦~
来源:https://blog.csdn.net/weixin_47723549/article/details/125498377
猜你喜欢
- 前言最近因为业务需求,就写了这个脚本,脚本完成的任务是从FTP上下载一个目录,大家都知道从FTP上下载一个文件可用用get命令,下载多个文件
- Windows下ORACLE完全卸载:使用OUI可以卸载数据库,但卸载后注册表和文件系统内仍会有部分残留。这些残留不仅占用磁盘空间,而且影响
- jscript 5.7 发布修复了不少ie javascript内存泄露的问题。但是leak依然存在。当我们频繁使用 setInterval
- XPath(XML Path language)是一种处理XML文档段的语言。XSLT(Extensible Stylesheet Lang
- b 和 i 标签在现在的 Web 标准潜规则中是不推荐使用,甚至是反对使用的,因为认为他们只是“表现”粗体和斜体,而没有任何“语义”。更多的
- 先来思考一个问题,B站一个视频的弹幕最多会有多少?比较多的会有2000条吧,这么多数据,B站肯定是不会直接把弹幕和这个视频绑在一起的。也就是
- python的使用之所以方便,原因之一就是各种数据类型各样轻松的转换,例如numpy数组和list的相互转换,只需要函数方法的使用就可以处理
- IDEA 插件安装 步骤IDEA里面,选择打开 File --> Settings --> Plugins在Plugins里面,
- 任务详情给定一各地 2016 年 1 月和 2 月各个时间点的温度表格,表格预览见页面下方。数据表的第二列表示当前时间,数据表第一行第三列到
- 近来实验室的师姐要 * 文,由于论文交稿时间临近,有一些杂活儿需要处理,作为实验室资历最浅的一批,我这个实习生也就责无旁贷地帮忙当个下手。今天
- 一、概述单机Mysql8数据库服务器运行过程中突然断电,导致数据库崩溃,无法重启。二、查找原因查看mysql运行错误日志:WIN-SOTMI
- 系统默认是torch.FloatTensor类型data = torch.Tensor(2,3)是一个2*3的张量,类型为FloatTens
- 1.对于RGB三通道图片,直接用两层for循环的话,效率比较低2.可以先将RGB图片转为灰度图片,再利用numpy.where的广播机制统计
- 应用背景背景:“由于工作需要可能需要对一些文件进行重命名的处理,但是可能操作起来比较烦,点错了就命名失败或者没带鼠标,用控制板操作起来比较麻
- 前言本文参考了以下代码Windows系统环境下Python脚本实现全局“划词复制”功能from py
- 序列是Python中最基本的数据结构。序列中的每个元素都分配一个数字 - 它的位置,或索引,第一个索引是0,第二个索引是1,依此类推。Pyt
- 本文主要介绍如何对多个文本进行读取,并采用正则表达式对其中的信息进行筛选,将筛选出来的信息存写到一个新文本。文本基础操作打开文件:open(
- 前言写爬虫的小伙伴可能遇到过这种情况:正当悠闲地喝着咖啡,满意地看着屏幕上的那一行行如流水般被爬下来的数据时,突然一个Error弹出,提示抓
- 简介我知道有很多文章和指南介绍在互联网上实现主-从复制。在主-从复制中,主机影响从机。但从数据库中的任何更改不会影响主数据库,这篇文章将帮助
- 本文实例总结了Python常用的小技巧。分享给大家供大家参考。具体分析如下:1. 获取本地mac地址:import uuidmac = uu