原文链接

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常见的几种并发模型框架的更多相关文章

  1. 构建自己的Java并发模型框架

    Java的多线程特性为构建高性能的应用提供了极大的方便,可是也带来了不少的麻烦.线程间同步.数据一致性等烦琐的问题须要细心的考虑,一不小心就会出现一些微妙的,难以调试的错误. 另外.应用逻辑和线程逻辑 ...

  2. 构建Java并发模型框架

    Java的多线程特性为构建高性能的应用提供了极大的方便,但是也带来了不少的麻烦.线程间同步.数据一致性等烦琐的问题需要细心的考虑,一不小心就会出现一些微妙的,难以调试的错误.另外,应用逻辑和线程逻辑纠 ...

  3. Java并发模型框架

    构建Java并发模型框架 Java的多线程特性为构建高性能的应用提供了极大的方便,但是也带来了不少的麻烦.线程间同步.数据一致性等烦琐的问题需要细心的考虑,一不小心就会出现一些微妙的,难以调试的错误. ...

  4. golang中的几种并发模式

    0.1.索引 https://blog.waterflow.link/articles/1663551951058 1.for- select模式 这种模式通常用在从多个通道读取数据 package ...

  5. 三分钟掌握共享内存 & Actor并发模型

    吃点好的,很有必要.今天介绍常见的两种并发模型: 共享内存&Actor 共享内存 面向对象编程中,万物都是对象,数据+行为=对象: 多核时代,可并行多个线程,但是受限于资源对象,线程之间存在对 ...

  6. memcached源码剖析4:并发模型

    memcached是一个典型的单进程系统.虽然是单进程,但是memcached内部通过多线程实现了master-worker模型,这也是服务端最常见的一种并发模型.实际上,除了master线程和wor ...

  7. 关于并发模型 Actor 和 CSP

    最近在看<七天七并发模型>这本书,在书上介绍了 Actor 和 CSP 这两种并发模型.这两种模型很像,但还是有一些不同的地方.看完之后,比较困扰的是: 在什么场合使用哪种模型比较好呢? ...

  8. 一网打尽 Java 并发模型

    本篇文章我们来探讨一下并发设计模型. 可以使用不同的并发模型来实现并发系统,并发模型说的是系统中的线程如何协作完成并发任务.不同的并发模型以不同的方式拆分任务,线程可以以不同的方式进行通信和协作. 并 ...

  9. Java并发模型(一)

    学习资料来自http://ifeve.com/java-concurrency-thread-directory/ 一.多线程 进程和线程的区别: 一个程序运行至少一个进程,一个进程至少包含一个线程. ...

随机推荐

  1. vue调试工具vue-devtools安装

    vue-devtools是一款基于chrome浏览器的插件,用于vue应用的调试,这款vue调试神器可以极大地提高我们的调试效率.帮助我们快速的调试开发vue应用. 这里介绍一下vue-devtool ...

  2. centos升级glibc2.23编译安装

    wget http://ftp.gnu.org/gnu/glibc/glibc-2.23.tar.gz tar -zxvf glibc-2.23.tar.gz cd glibc-2.23 mkdir ...

  3. 网络编程介绍,C/S 架构,网络通讯协议,osi七层

    网络编程: 什么是网络编程: 网络通常指的是计算机中的互联网,是由多台计算机通过网线或其他媒介相互链接组成的 编写基于网络的应用程序的过程序称之为网络编程 为什么要学习网络编程: 我们已经知道计算机, ...

  4. Linux C/C++基础——文件(上)

    1.文件指针 FILE* fp=NULL; fp指针,只调用了fopen(),在堆区分配空间,把地址返回给fp fp指针不是指向文件,fp指针和文件关联,fp内部成员保存在文件的状态 操作fp指针,不 ...

  5. 【DSP开发】【Linux开发】IIC设备驱动程序

    IIC设备是一种通过IIC总线连接的设备,由于其简单性,被广泛引用于电子系统中.在现代电子系统中,有很多的IIC设备需要进行相互之间通信 IIC总线是由PHILIPS公司开发的两线式串行总线,用于连接 ...

  6. python笔记之元祖

    元祖创建使用圆括号括起来,中间元素使用逗号隔开 如:tuple1 = (1,2,3,4) tuple2 = () 空元祖 #!/usr/bin/env python #-*-coding:utf-8- ...

  7. 10分钟学会web通讯的四种方式,短轮询、长轮询(comet)、长连接(SSE)、WebSocket

    一般看到标题我们一般会产生下面几个问题??? 什么是短轮询? 什么是长轮询? 长连接又是什么? wensocket怎么实现呢? 他们都能实现web通讯,区别在哪呢,哪个好用呢? 接下来我们就一个个来了 ...

  8. 【转贴】使用sar进行性能分析

    使用sar进行性能分析 https://www.cnblogs.com/bangerlee/articles/2545747.html 很早之前就看过 但是自己一直没用过.. 2012-06-12 0 ...

  9. 小记--------CDH版本启动cloudera manager UI界面

    首先需要启动mysql源数据库 server所在服务器的路径:/opt/cm-5.14.0/etc/cloudera-scm-server 下 查看配置文件: db.properties   查看my ...

  10. java的hashCode和equals为什么要同时重写?

    原因: java规范:相等的对象必须具有相等的散列码(hashCode) 同时对于HashSet和HashMap这些基于散列值(hash)实现的类.key的判断是通过hashCode完成,且散列也是通 ...