golang several common concurrency model framework

 

Description link

Package main 
 
Import ( 
	"FMT" 
	"Math / RAND" 
	"OS" 
	"Runtime" 
	"Sync" 
	"Sync / Atomic" 
	"Time" 
) 
 
type Scenario struct { 
	the Name String 
	the Description [] String 
	Examples [] String 
	runExample FUNC () 
} 
var Scenario & = {S1 
	the Name: "S1", 
	the Description: [] {String 
		"simple tasks executed concurrently", 
	}, 
	Examples: [] {String 
		"rear concurrent requests such an interface", 
	}, 
	runExample: RunScenario1, 
} 
 
& Scenario S2 = {var 
	the Name: "S2", 
	the Description:[] {String 
		"predetermined time duration high concurrency model" 
	}, 
	Examples: [] {String
		"Within a predetermined time, sustained high concurrent requests backend service to prevent the service infinite loop", 
	}, 
	runExample: RunScenario2, 
} 
 
var S3 = & Scenario { 
	the Name: "S3", 
	String {[]: the Description 
		"large amount of data based on model of concurrent tasks, the pool goroutine worker ", 
	}, 
	Examples: [] {String 
		" such as technical support to give a customer deletes several TB / GB file ", 
	}, 
	runExample: RunScenario3, 
} 
 
var s4 = {& Scenario 
	the Name : "S4", 
	the Description: [] String { 
		"wait for asynchronous execution result of the task (goroutines + SELECT + Channel)", 
	}, 
	Examples: [] String { 
		"", 
	}, 
	runExample: RunScenario4, 
} 
 
var S5 = & Scenario { 
	the Name : "s5","s5",
	Description: []string{
		"The timing of the feedback result (Ticker)", 
	},
	Examples: [] {String 
		"such as testing performance of the interface to upload, to give real-time indicators: throughput, IOPS, the success rate", 
	}, 
	runExample: RunScenario5, 
} 
 
var Scenarios [] * Scenario 
 
FUNC the init () { 
	Scenarios = the append (scenarios, S1) 
	scenarios = the append (scenarios, S2) 
	scenarios = the append (scenarios, S3) 
	scenarios = the append (scenarios, S4) 
	scenarios = the append (scenarios, S5) 
} 
 
// concurrency and common synchronization scenario 
func main ( ) { 
	IF len (os.Args). 1 == { 
		fmt.Println ( "Please choose a scene ==>") 
		for _, SC: = Range scenarios { 
			fmt.Printf ( "scene:% 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 ( "% S Got Result", C) 
	Case <-time.After (time.Duration (30 * time.Second) ): 
		fmt.Errorf ( "specified time not result") 
	} 
} 
 
var doUploadMock = FUNC () {BOOL 
	time.sleep (time.Millisecond time.Duration * (100)) 
	n-: = rand.Intn (100) 
	n-IF> {50 
		return to true 
	} the else { 
		return to false 
	} 
} 
 
// scenario 5: feedback result (Ticker) timing 
// test performance of the interface to upload, to give real-time indicators: throughput, the success rate 
 
func RunScenario5 () { 
	totalSize: Int64 = (0) 
	The totalCount: = Int64 (0) 
	totalErr: = Int64 (0) 
 
	concurrencyCount: = runtime.NumCPU () 
	STOP: = the 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
			}
		}
 
	}
}

  

 

Guess you like

Origin www.cnblogs.com/-wenli/p/11206506.html