Go简单实现协程池的实现示例

 更新时间:2022年06月29日 08:26:57   作者:爪哇盘古  
本文主要介绍了Go简单实现协程池的实现示例,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧

首先就是进程、线程、协程讲解老三样。

进程: 本质上是一个独立执行的程序,进程是操作系统进行资源分配和调度的基本概念,操作系统进行资源分配和调度的一个独立单位。

线程: 是操作系统能够进行运算调度的最小单位。它被包含在进程之中,是进程中的实际运作单位。一个进程中可以并发多个线程,每条线程执行不同的任务,切换受系统控制。

协程:  又称为微线程,是一种用户态的轻量级线程,协程不像线程和进程需要进行系统内核上的上下文切换,协程的上下文切换是由用户自己决定的,有自己的上下文,所以说是轻量级的线程,也称之为用户级别的线程就叫协程,一个线程可以多个协程,线程进程都是同步机制,而协程则是异步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来监听管道是否有数据,协程池的实现就是合理利用管道。可以根据该思路来进行优化封装一个属于自己的协程池哦~

到此这篇关于Go简单实现协程池的实现示例的文章就介绍到这了,更多相关Go 协程池内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • 完美解决go Fscanf 在读取文件时出现的问题

    完美解决go Fscanf 在读取文件时出现的问题

    这篇文章主要介绍了完美解决go Fscanf 在读取文件时出现的问题,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧
    2021-03-03
  • golang gorm的关系关联实现示例

    golang gorm的关系关联实现示例

    这篇文章主要为大家介绍了golang gorm的关系关联实现示例,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步早日升职加薪
    2022-04-04
  • Go并发编程sync.Cond的具体使用

    Go并发编程sync.Cond的具体使用

    Go 标准库提供 Cond 原语的目的是,为等待 / 通知场景下的并发问题提供支持,本文主要介绍了Go并发编程sync.Cond的具体使用,具有一定的参考价值,感兴趣的可以了解一下
    2022-05-05
  • 详解Golang编程中的常量与变量

    详解Golang编程中的常量与变量

    这篇文章主要介绍了详解Golang编程中的常量与变量,是Go语言入门学习中的基础知识,需要的朋友可以参考下
    2015-10-10
  • golang结构化日志log/slog包之slog.Record的用法简介

    golang结构化日志log/slog包之slog.Record的用法简介

    这篇文章主要为大家详细介绍了golang结构化日志log/slog包中slog.Record结构体的使用方法和需要注意的点,文中的示例代码讲解详细,需要的可以学习一下
    2023-10-10
  • Go实现自动解压缩包以及读取docx/doc文件内容详解

    Go实现自动解压缩包以及读取docx/doc文件内容详解

    在开发过程中,我们常常需要处理压缩包和文档文件。本文将介绍如何使用Go语言自动解压缩包和读取docx/doc文件,需要的可以参考一下
    2023-03-03
  • Golang 统计字符串字数的方法示例

    Golang 统计字符串字数的方法示例

    本篇文章主要介绍了Golang 统计字符串字数的方法示例,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧
    2018-05-05
  • Go中Vendo机制的使用

    Go中Vendo机制的使用

    自Go1.6起,Go语言正式启用vendor机制,允许将项目依赖放入项目内的vendor目录,类似私有GOPATH,本文就来介绍一下Vendo机制的使用,感兴趣的可以了解一下
    2024-10-10
  • Go语言实战之实现一个简单分布式系统

    Go语言实战之实现一个简单分布式系统

    如今很多云原生系统、分布式系统,例如 Kubernetes,都是用 Go 语言写的,这是因为 Go 语言天然支持异步编程。本篇文章将介绍如何用 Go 语言编写一个简单的分布式系统,需要的小伙伴开业跟随小编一起学习一下
    2022-10-10
  • Go编译32位GNU静态链接库的方法

    Go编译32位GNU静态链接库的方法

    Go链接库系统的难用可谓是人尽皆知,不同Go版本编译出来的不兼容,而且只支持GNU的,不能编译出Windows上的dll和lib。这篇文章给大家介绍Go编译32位GNU静态链接库的方法,感兴趣的朋友一起看看吧
    2020-05-05

最新评论