Go簡單實現(xiàn)協(xié)程池的實現(xiàn)示例
首先就是進程、線程、協(xié)程講解老三樣。
進程: 本質(zhì)上是一個獨立執(zhí)行的程序,進程是操作系統(tǒng)進行資源分配和調(diào)度的基本概念,操作系統(tǒng)進行資源分配和調(diào)度的一個獨立單位。
線程: 是操作系統(tǒng)能夠進行運算調(diào)度的最小單位。它被包含在進程之中,是進程中的實際運作單位。一個進程中可以并發(fā)多個線程,每條線程執(zhí)行不同的任務,切換受系統(tǒng)控制。
協(xié)程: 又稱為微線程,是一種用戶態(tài)的輕量級線程,協(xié)程不像線程和進程需要進行系統(tǒng)內(nèi)核上的上下文切換,協(xié)程的上下文切換是由用戶自己決定的,有自己的上下文,所以說是輕量級的線程,也稱之為用戶級別的線程就叫協(xié)程,一個線程可以多個協(xié)程,線程進程都是同步機制,而協(xié)程則是異步Java的原生語法中并沒有實現(xiàn)協(xié)程,目前python、Lua和GO等語言支持。
關(guān)系:一個進程可以有多個線程,它允許計算機同時運行兩個或多個程序。線程是進程的最小執(zhí)行單位,CPU
的調(diào)度切換的是進程和線程,進程和線程多了之后調(diào)度會消耗大量的CPU,CPU上真正運行的是線程,線程可
以對應多個協(xié)程。
MPG模型
Go協(xié)程中有三個關(guān)鍵實體:
- M(machine): 工作線程,由操作系統(tǒng)調(diào)度。應該就是通常所說的內(nèi)核線程。
- P(processor): 處理器(非CPU),代表著運行Go代碼的必要資源,以及調(diào)度goroutine的能力。個人覺得可以當作擁有自主調(diào)度權(quán)的算法模塊,用于工作竊?。╳ork stealing)。
- G(gooutine): Go協(xié)程,輕量級用戶線程。主要包含執(zhí)行棧和調(diào)度管理器。這里的調(diào)度管理器指的是,統(tǒng)一并管理調(diào)度資源,等待被調(diào)度。
Go協(xié)程的特點
(1)有獨立的??臻g
(2)共享程序的堆空間
(3)協(xié)程調(diào)度由用戶控制(進程的控制是有操作系統(tǒng)控制,程序員不能控制)
(4)協(xié)程是輕量級的線程
通道的特性
Go語言中的通道(channel)是一種特殊的類型。在任何時候,同時只能有一個 goroutine 訪問通道進行發(fā)送和獲取數(shù)據(jù)。goroutine 間通過通道就可以通信。
通道像一個傳送帶或者隊列,總是遵循先入先出(First In First Out)的規(guī)則,保證收發(fā)數(shù)據(jù)的順序。
當然協(xié)程的輕量性并不代表可以隨意濫用,畢竟還是存在資源的消耗。本文主要講解go的協(xié)程池的實現(xiàn)原理,利用select來監(jiān)聽任務?!敬a僅用作實現(xiàn)原理,想更優(yōu)雅可以在該原理基礎(chǔ)上自行優(yōu)化】
廢話不多說直接上代碼!
package main import ( "strconv" "time" ) /** 協(xié)程池 */ //全局任務管道地址數(shù)組 var arr []*chan func() //啟動任務數(shù)量 var num = 10 //默認管道下標0 var index = 0 //任務開關(guān) var static = false func run(f *chan func()){ println("等待咯") for static == true { select { case fu:=<-*f : // 檢測有沒有數(shù)據(jù)可讀 // 一旦成功讀取到數(shù)據(jù),則進行該case處理語句 fu() default: //println(f) //println("無數(shù)據(jù)") } time.Sleep(time.Duration(1)*time.Second) } } //啟動任務函數(shù) func Start(){ static = true for i:=0;i<num;i++ { //make一個管道地址 c:=make(chan func(),1) println(&c) //將該地址存入全局數(shù)組中 arr = append(arr,&c) //地址傳入任務函數(shù) go run(&c) } } //插入任務 func add(str string) { //此處不是很優(yōu)雅,自行優(yōu)化實現(xiàn)。 if(index >= num-1){ index = 0 }else{ index++ } //向地址管道傳入函數(shù) *arr[index] <- func() { println(str) } } //停止任務 func stop() { //終止任務for static = false //清空管道數(shù)組 arr = []*chan func(){} } func main() { Start() println("開始執(zhí)行寫入管道") 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來監(jiān)聽管道是否有數(shù)據(jù),協(xié)程池的實現(xiàn)就是合理利用管道。可以根據(jù)該思路來進行優(yōu)化封裝一個屬于自己的協(xié)程池哦~
到此這篇關(guān)于Go簡單實現(xiàn)協(xié)程池的實現(xiàn)示例的文章就介紹到這了,更多相關(guān)Go 協(xié)程池內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
Go語言實現(xiàn)一個Http Server框架(二) Server的抽象
上一篇文章對http庫的基本使用做了說明,這篇文章主要介紹了如何實現(xiàn)一個簡單地httpServer,文中代碼示例非常詳細,感興趣的朋友可以參考下2023-04-04Go語言中GORM存取數(shù)組/自定義類型數(shù)據(jù)
在使用gorm時往往默認的數(shù)據(jù)類型不滿足我們的要求,需要使用一些自定義數(shù)據(jù)類型作為字段類型,下面這篇文章主要給大家介紹了關(guān)于Go語言中GORM存取數(shù)組/自定義類型數(shù)據(jù)的相關(guān)資料,需要的朋友可以參考下2023-01-01基于go+vue實現(xiàn)的golang每日新聞數(shù)據(jù)瀏覽與檢索平臺(推薦)
gonews是基于 go+vue 實現(xiàn)的golang每日新聞瀏覽與檢索平臺,本文通過實例代碼給大家講解,介紹的非常詳細,具有參考借鑒價值,需要的朋友參考下吧2018-01-01golang HTTP 服務器 處理 日志/Stream流的操作
這篇文章主要介紹了golang HTTP 服務器 處理 日志/Stream流的操作,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧2020-12-12Go語言實現(xiàn)操作MySQL的基礎(chǔ)知識總結(jié)
這篇文章主要總結(jié)一下怎么使用Go語言操作MySql數(shù)據(jù)庫,文中的示例代碼講解詳細,需要的朋友可以參考以下內(nèi)容,希望對大家有所幫助2022-09-09