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/ 一.多线程 进程和线程的区别: 一个程序运行至少一个进程,一个进程至少包含一个线程. ...
随机推荐
- 链表反转 C++
ListNode* reverse1(ListNode* pHead) { if(pHead == NULL) return NULL; ListNode * p1 = NULL; ListNode ...
- javascript控制流程语句
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/ ...
- 五十四:WTForms表单验证之自定义表单验证器
如果想要对表单中的某个字段进行自定义验证,则需要对这个字段进行单独的验证1.定义一个方法,命名规则为:validate_字段名(self, filed)2.在方法中,使用filed.data获取字段的 ...
- 如何使用Pythonapi函数写股票策略
如何使用Python api 函数写股票策略 写策略需要了解的语法包括两方面,一方面是语言本身的语法(包括相关库),另一方面是量化平台提供的api.量化平台提供的api帮助文件里都有了,本文主要介绍写 ...
- .NET 实现复制粘贴功能
老是把自己当作珍珠,就时时有怕被埋没的痛苦.把自己当作泥土吧,让众人把你踩成一条道路. -----<泥土>鲁藜 .NET如何实现复制粘贴功能,具体代码如下: aspx文件: <div ...
- PYTHON TDD学习(一)-->Python 3.4版本环境安装Django及其启动
1.安装Python3.4版本,原因:3.4及其以后版本默认自带pip工具,非常好用 2.django 安装命令(c:\Python34\Scripts):pip install django 3.s ...
- Java工程师研发面经大合集
百度研发面经整合版 软件研发工程师 基础研发工程师 百度智能云 百度核心搜索部 百度今年的提前批有点奇怪,好像都不走流程,牛客上好几个百度内推的帖子,我投了几个,基本上都是百度智能云的,当然也有其他部 ...
- python高级 之(五) --- 文件操作
文件操作 """ 在程序中操作的文件内容: 1. 读取文件中的内容 2. 向文件中写入内容 首先: 在程序中与文件建立一个通道,通过通道操作文件指针,达到所要的结果 向文 ...
- 【POJ - 3279】Fliptile(经典翻转问题)
-->Fliptile 直接中文翻译:Descriptions: 给你一个01矩阵,矩阵大小为M x N.(1 <= M , N <= 15)每次操作选择一个格子,使得该格子与上下左 ...
- 【AMAD】newspaper -- 爬取/提取新闻网页中的文本,元数据
动机 简介 用法 源码分析 个人评分 动机 新闻网页,结构大多是类似的. 所以,能不能用一种通用的爬取方法来提取其中的数据? 简介 Newspapaer1受到requests那种简单性API的启发,通 ...