crm开发定制Go简单实现协程池

crm开发定制首先就是进程、线程、crm开发定制协程讲解老三样。

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

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


协程:  又称为微线程,是一种用户态的轻量级线程,不像线程和进程需要进行系统内核上的上下文切换,协程的上下文切换是由用户自己决定的,有自己的上下文,所以说是轻量级的线程,也称之为用户级别的线程就叫协程,一个线程可以多个协程,线程进程都是同步机制,而协程则是异步Java的原生语法中并没有实现协程,目前python、Lua和GO等语言支持。


关系:一个进程可以有多个线程,它允许计算机同时运行两个或多个程序。线程是进程的最小执行单位,CPU
的调度切换的是进程和线程,进程和线程多了之后调度会消耗大量的CPU,CPU上真正运行的是线程,线程可
以对应多个协程。

 golang协程

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来监听任务。【代码仅用作实现原理,想更优雅可以在该原理基础上自行优化】

废话不多说直接上代码!

  1. package main
  2. import (
  3. "strconv"
  4. "time"
  5. )
  6. /**
  7. 协程池
  8. */
  9. //全局任务管道地址数组
  10. var arr []*chan func()
  11. //启动任务数量
  12. var num = 10
  13. //默认管道下标0
  14. var index = 0
  15. //任务开关
  16. var static = false
  17. func run(f *chan func()){
  18. println("等待咯")
  19. for static == true {
  20. select {
  21. case fu:=<-*f : // 检测有没有数据可读
  22. // 一旦成功读取到数据,则进行该case处理语句
  23. fu()
  24. default:
  25. //println(f)
  26. //println("无数据")
  27. }
  28. time.Sleep(time.Duration(1)*time.Second)
  29. }
  30. }
  31. //启动任务函数
  32. func Start(){
  33. static = true
  34. for i:=0;i<num;i++ {
  35. //make一个管道地址
  36. c:=make(chan func(),1)
  37. println(&c)
  38. //将该地址存入全局数组中
  39. arr = append(arr,&c)
  40. //地址传入任务函数
  41. go run(&c)
  42. }
  43. }
  44. //插入任务
  45. func add(str string) {
  46. //此处不是很优雅,自行优化实现。
  47. if(index >= num-1){
  48. index = 0
  49. }else{
  50. index++
  51. }
  52. //向地址管道传入函数
  53. *arr[index] <- func() {
  54. println(str)
  55. }
  56. }
  57. //停止任务
  58. func stop() {
  59. //终止任务for
  60. static = false
  61. //清空管道数组
  62. arr = []*chan func(){}
  63. }
  64. func main() {
  65. Start()
  66. println("开始执行写入管道")
  67. println(len(arr))
  68. for i:=0;i<1000000000;i++ {
  69. add("传入的i:"+strconv.Itoa(i))
  70. }
  71. time.Sleep(time.Duration(2)*time.Second)
  72. stop()
  73. //time.Sleep(time.Duration(100)*time.Second)
  74. }

原理很简单,就是合理使用select来监听管道是否有数据,协程池的实现就是合理利用管道。可以根据该思路来进行优化封装一个属于自己的协程池哦~

对于优化建议,有牛可评论,相互学习!

网站建设定制开发 软件系统开发定制 定制软件开发 软件开发定制 定制app开发 app开发定制 app开发定制公司 电商商城定制开发 定制小程序开发 定制开发小程序 客户管理系统开发定制 定制网站 定制开发 crm开发定制 开发公司 小程序开发定制 定制软件 收款定制开发 企业网站定制开发 定制化开发 android系统定制开发 定制小程序开发费用 定制设计 专注app软件定制开发 软件开发定制定制 知名网站建设定制 软件定制开发供应商 应用系统定制开发 软件系统定制开发 企业管理系统定制开发 系统定制开发