golang常见的几种并发模型框架
package main import ( "fmt" "math/rand" "os" "runtime" "sync" "sync/atomic" "time" ) type Scenario struct { Name string Description []string Examples []string RunExample func() } var s1 = &Scenario{ Name: "s1", Description: []string{ "简单并发执行任务", }, Examples: []string{ "比如并发的请求后端某个接口", }, RunExample: RunScenario1, } var s2 = &Scenario{ Name: "s2", Description: []string{ "持续一定时间的高并发模型", }, Examples: []string{ "在规定时间内,持续的高并发请求后端服务, 防止服务死循环", }, RunExample: RunScenario2, } var s3 = &Scenario{ Name: "s3", Description: []string{ "基于大数据量的并发任务模型, goroutine worker pool", }, Examples: []string{ "比如技术支持要给某个客户删除几个TB/GB的文件", }, RunExample: RunScenario3, } var s4 = &Scenario{ Name: "s4", Description: []string{ "等待异步任务执行结果(goroutine+select+channel)", }, Examples: []string{ "", }, RunExample: RunScenario4, } var s5 = &Scenario{ Name: "s5", Description: []string{ "定时的反馈结果(Ticker)", }, Examples: []string{ "比如测试上传接口的性能,要实时给出指标: 吞吐率,IOPS,成功率等", }, RunExample: RunScenario5, } var Scenarios []*Scenario func init() { Scenarios = append(Scenarios, s1) Scenarios = append(Scenarios, s2) Scenarios = append(Scenarios, s3) Scenarios = append(Scenarios, s4) Scenarios = append(Scenarios, s5) } // 常用的并发与同步场景 func main() { if len(os.Args) == 1 { fmt.Println("请选择使用场景 ==> ") for _, sc := range Scenarios { fmt.Printf("场景: %s ,", sc.Name) printDescription(sc.Description) } return } for _, arg := range os.Args[1:] { sc := matchScenario(arg) if sc != nil { printDescription(sc.Description) printExamples(sc.Examples) sc.RunExample() } } } func printDescription(str []string) { fmt.Printf("场景描述: %s \n", str) } func printExamples(str []string) { fmt.Printf("场景举例: %s \n", str) } func matchScenario(name string) *Scenario { for _, sc := range Scenarios { if sc.Name == name { return sc } } return nil } var doSomething = func(i int) string { time.Sleep(time.Millisecond * time.Duration(10)) fmt.Printf("Goroutine %d do things .... \n", i) return fmt.Sprintf("Goroutine %d", i) } var takeSomthing = func(res string) string { time.Sleep(time.Millisecond * time.Duration(10)) tmp := fmt.Sprintf("Take result from %s.... \n", res) fmt.Println(tmp) return tmp } // 场景1: 简单并发任务 func RunScenario1() { count := 10 var wg sync.WaitGroup for i := 0; i < count; i++ { wg.Add(1) go func(index int) { defer wg.Done() doSomething(index) }(i) } wg.Wait() } // 场景2: 按时间来持续并发 func RunScenario2() { timeout := time.Now().Add(time.Second * time.Duration(10)) n := runtime.NumCPU() waitForAll := make(chan struct{}) done := make(chan struct{}) concurrentCount := make(chan struct{}, n) for i := 0; i < n; i++ { concurrentCount <- struct{}{} } go func() { for time.Now().Before(timeout) { <-done concurrentCount <- struct{}{} } waitForAll <- struct{}{} }() go func() { for { <-concurrentCount go func() { doSomething(rand.Intn(n)) done <- struct{}{} }() } }() <-waitForAll } // 场景3:以 worker pool 方式 并发做事/发送请求 func RunScenario3() { numOfConcurrency := runtime.NumCPU() taskTool := 10 jobs := make(chan int, taskTool) results := make(chan int, taskTool) var wg sync.WaitGroup // workExample workExampleFunc := func(id int, jobs <-chan int, results chan<- int, wg *sync.WaitGroup) { defer wg.Done() for job := range jobs { res := job * 2 fmt.Printf("Worker %d do things, produce result %d \n", id, res) time.Sleep(time.Millisecond * time.Duration(100)) results <- res } } for i := 0; i < numOfConcurrency; i++ { wg.Add(1) go workExampleFunc(i, jobs, results, &wg) } totalTasks := 100 wg.Add(1) go func() { defer wg.Done() for i := 0; i < totalTasks; i++ { n := <-results fmt.Printf("Got results %d \n", n) } close(results) }() for i := 0; i < totalTasks; i++ { jobs <- i } close(jobs) wg.Wait() } // 场景4: 等待异步任务执行结果(goroutine+select+channel) func RunScenario4() { sth := make(chan string) result := make(chan string) go func() { id := rand.Intn(100) for { sth <- doSomething(id) } }() go func() { for { result <- takeSomthing(<-sth) } }() select { case c := <-result: fmt.Printf("Got result %s ", c) case <-time.After(time.Duration(30 * time.Second)): fmt.Errorf("指定时间内都没有得到结果") } } var doUploadMock = func() bool { time.Sleep(time.Millisecond * time.Duration(100)) n := rand.Intn(100) if n > 50 { return true } else { return false } } // 场景5: 定时的反馈结果(Ticker) // 测试上传接口的性能,要实时给出指标: 吞吐率,成功率等 func RunScenario5() { totalSize := int64(0) totalCount := int64(0) totalErr := int64(0) concurrencyCount := runtime.NumCPU() stop := make(chan struct{}) fileSizeExample := int64(10) timeout := 10 // seconds to stop go func() { for i := 0; i < concurrencyCount; i++ { go func(index int) { for { select { case <-stop: return default: break } res := doUploadMock() if res { atomic.AddInt64(&totalCount, 1) atomic.AddInt64(&totalSize, fileSizeExample) } else { atomic.AddInt64(&totalErr, 1) } } }(i) } }() t := time.NewTicker(time.Second) index := 0 for { select { case <-t.C: index++ tmpCount := atomic.LoadInt64(&totalCount) tmpSize := atomic.LoadInt64(&totalSize) tmpErr := atomic.LoadInt64(&totalErr) fmt.Printf("吞吐率: %d,成功率: %d \n", tmpSize/int64(index), tmpCount*100/(tmpCount+tmpErr)) if index > timeout { t.Stop() close(stop) return } } } }
golang常见的几种并发模型框架的更多相关文章
- 构建自己的Java并发模型框架
Java的多线程特性为构建高性能的应用提供了极大的方便,可是也带来了不少的麻烦.线程间同步.数据一致性等烦琐的问题须要细心的考虑,一不小心就会出现一些微妙的,难以调试的错误. 另外.应用逻辑和线程逻辑 ...
- 构建Java并发模型框架
Java的多线程特性为构建高性能的应用提供了极大的方便,但是也带来了不少的麻烦.线程间同步.数据一致性等烦琐的问题需要细心的考虑,一不小心就会出现一些微妙的,难以调试的错误.另外,应用逻辑和线程逻辑纠 ...
- Java并发模型框架
构建Java并发模型框架 Java的多线程特性为构建高性能的应用提供了极大的方便,但是也带来了不少的麻烦.线程间同步.数据一致性等烦琐的问题需要细心的考虑,一不小心就会出现一些微妙的,难以调试的错误. ...
- golang中的几种并发模式
0.1.索引 https://blog.waterflow.link/articles/1663551951058 1.for- select模式 这种模式通常用在从多个通道读取数据 package ...
- 三分钟掌握共享内存 & Actor并发模型
吃点好的,很有必要.今天介绍常见的两种并发模型: 共享内存&Actor 共享内存 面向对象编程中,万物都是对象,数据+行为=对象: 多核时代,可并行多个线程,但是受限于资源对象,线程之间存在对 ...
- memcached源码剖析4:并发模型
memcached是一个典型的单进程系统.虽然是单进程,但是memcached内部通过多线程实现了master-worker模型,这也是服务端最常见的一种并发模型.实际上,除了master线程和wor ...
- 关于并发模型 Actor 和 CSP
最近在看<七天七并发模型>这本书,在书上介绍了 Actor 和 CSP 这两种并发模型.这两种模型很像,但还是有一些不同的地方.看完之后,比较困扰的是: 在什么场合使用哪种模型比较好呢? ...
- 一网打尽 Java 并发模型
本篇文章我们来探讨一下并发设计模型. 可以使用不同的并发模型来实现并发系统,并发模型说的是系统中的线程如何协作完成并发任务.不同的并发模型以不同的方式拆分任务,线程可以以不同的方式进行通信和协作. 并 ...
- Java并发模型(一)
学习资料来自http://ifeve.com/java-concurrency-thread-directory/ 一.多线程 进程和线程的区别: 一个程序运行至少一个进程,一个进程至少包含一个线程. ...
随机推荐
- Linux上安装Python3
1. 安装支持包 yum -y groupinstall "Development tools" yum -y install zlib-devel bzip2-devel ope ...
- 提问(prompt)
prompt弹出消息对话框,通常用于询问一些需要与用户交互的信息.弹出消息对话框(包含一个确定按钮.取消按钮与一个文本输入框). 语法: prompt(str1, str2); 参数说明: str1: ...
- Orcal数据类型总结
一.Oracle中的varchar2类型 我们在Oracle数据库存储的字符数据一般是用VARCHAR2.VARCHAR2既分PL/SQL Data Types中的变量类型,也分Oracle Data ...
- LC 963. Minimum Area Rectangle II
Given a set of points in the xy-plane, determine the minimum area of any rectangle formed from these ...
- javascript之Location对象
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/ ...
- ip地址后面的斜杠24
ip地址后面的斜杠24表示掩码位是24位的,即用32位二进制表示的子网掩码中有连续的24个“1”:11111111 11111111 11111111 00000000,将其转化为十进制,就是:255 ...
- 七十九:flask.Restful之flask-Restful蓝图与渲染模板
1.flask-Restful与蓝图结合使用如果要在蓝图中使用flask-Restful,那么在创建Api对象的时候,就不应该使用app,而是蓝图,如果有多个蓝图,则需在每一个蓝图里面创建一个Api对 ...
- php register_shutdown_function响应error 配合error_get_last 捕获错误
转自: http://blog.csdn.net/a757291228/article/details/62231125 //一个函数,用来响应 register_shutdown_function ...
- 【转】Linux curl命令详解
[From]https://www.cnblogs.com/duhuo/p/5695256.html 命令:curl 在Linux中curl是一个利用URL规则在命令行下工作的文件传输工具,可以说是一 ...
- redis安装及遇到的坑-linux
获取Redis安装包“redis-4.0.8.tar.gz”,上传Linux服务器; 使用root用户解压: tar zxvf redis-4.0.8.tar.gz -C /usr/local/; 进 ...