Go_goroutine和channel结合

Posted yzg-14

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Go_goroutine和channel结合相关的知识,希望对你有一定的参考价值。

1. 案例1

技术图片

package main

import (
	"fmt"
	_ "time"
)

//write Data
func writeData(intChan chan int) {
	for i := 1; i <= 50; i++ {
		//放入数据
		intChan <- i //
		fmt.Println("writeData ", i)
		//time.Sleep(time.Second)
	}
	close(intChan) //关闭
}

//read data
func readData(intChan chan int, exitChan chan bool) {

	for {
		v, ok := <-intChan
		if !ok { //Python中的not
			break
		}
		//time.Sleep(time.Second)
		fmt.Printf("readData 读到数据=%v
", v)
	}
	//readData 读取完数据后,即任务完成
	exitChan <- true
	close(exitChan)

}

func main() {

	//创建两个管道
	intChan := make(chan int, 10)
	exitChan := make(chan bool, 1)

	go writeData(intChan)
	go readData(intChan, exitChan)

	//time.Sleep(time.Second * 10)
	for {
		_, ok := <-exitChan
		if !ok {
			break
		}
	}

}

2. 案例2(代码在案例1)

技术图片

技术图片

 3. 案例3

技术图片

技术图片

package main

import (
	"fmt"
	_ "time"
	"time"
)

//向 intChan放入 1-8000个数
func putNum(intChan chan int) {

	for i := 1; i <= 200000; i++ {
		intChan <- i
	}
	//关闭intChan
	close(intChan)
}

//从 intChan取出数据,并判断是否为素数,如果是,就放入到primeChan
func primeNum(intChan chan int, primeChan chan int, exitChan chan bool) {

	//使用for 循环
	// var num int
	var flag bool
	for {
		//time.Sleep(time.Millisecond * 10)
		num, ok := <-intChan

		if !ok {
			break
		}
		flag = true //假设是素数
		//判断num是不是素数
		for i := 2; i < num; i++ {
			if num%i == 0 { //说明该num不是素数
				flag = false
				break
			}
		}

		if flag {
			//将这个数就放入到primeChan
			primeChan <- num
		}
	}

	//fmt.Println("有一个primeNum 协程因为取不到数据,退出")
	//这里我们还不能关闭 primeChan
	//向 exitChan 写入true
	exitChan <- true

}

func main() {

	intChan := make(chan int, 200000)
	primeChan := make(chan int, 200000) //放入结果
	//标识退出的管道
	exitChan := make(chan bool, 12) // 12个
	start := time.Now().Unix()

	//开启一个协程,向 intChan放入 1-8000个数
	go putNum(intChan)
	//开启12个协程,从 intChan取出数据,并判断是否为素数,如果是,就放入到primeChan
	//电脑是12个逻辑cpu
	for i := 0; i < 12; i++ {
		go primeNum(intChan, primeChan, exitChan)
	}

	//这里我们主线程,进行处理
	go func() {
		for i := 0; i < 12; i++ {
			<-exitChan
		}

		end := time.Now().Unix()
		fmt.Println("使用协程耗时=", end-start)

		//当我们从exitChan 取出了12个结果,就可以放心的关闭primeChan
		close(primeChan)
	}()

	//遍历我们的 primeChan ,把结果取出
	for {
		res, ok := <-primeChan
		if !ok {
			break
		}
		//将结果输出
		fmt.Printf("素数=%d
", res)
	}

	fmt.Println("main线程退出")

}

技术图片

普通的方法

package main
import (
	"time"
	"fmt"
)

func main() {

	start := time.Now().Unix()
	for num := 1; num <= 200000; num++ {

		flag := true //假设是素数
		//判断num是不是素数
		for i := 2; i < num; i++ {
			if num % i == 0 {//说明该num不是素数
				flag = false
				break
			}
		}

		if flag {
			//将这个数就放入到primeChan
			//primeChan<- num
		}

	}
	end := time.Now().Unix()
	fmt.Println("普通的方法耗时=", end - start)

}

技术图片

 

 

以上是关于Go_goroutine和channel结合的主要内容,如果未能解决你的问题,请参考以下文章

57 java编程思想——创建窗口和程序片 可视编程和Beans

Go+ for结合<-

itchat和matplotlib的结合使用

在 golang 中创建一片缓冲通道

[转帖]go 的goroutine 以及 channel 的简介.

重磅:Flume1-7结合kafka讲解