您的位置 首页 golang

golang goroutine与channel入门练习题一

题目

用goroutine与channel实现,计算出1-200内的素数

本例是一个goroutine与channel结合使用的必会题目,需要对goroutine与channel有一定基础知识才能完成。

结题思路

  1. 使用一个管道inChan保存需要处理的数据,启动一个协程writeData,依次将数据放入管道inChan
  2. 使用一个管道exitChan保存退出标记位,用于判断所有协程是否完成。
  3. 阻塞主线程,一直等到所有协程都完成

代码实现

 package main

import (
	"fmt"
	"runtime"
)
/*
1. 启动一个协程writedata将200个数据到,管道inChan
2. 启动一个readdata从管道inChan读数据,判断读到的数据是否素数,如果是素数则打印。
3. 管道exitChan用于判断所有协程是否都完成
 */

// 判断一个数是否是素数
func isPrieme(num int) bool {
	for i:=2;i<num;i++{
		if num % i == 0 {
			return false
		}
	}
	return true
}

// 将200个数写入管道
func writeData(inChan chan int)  {
	// 依次写入200个数到管道inChan
	for i:=1;i<=200;i++ {
		inChan <- i
		//time.Sleep(time.Second*2)
	}
	// 写入完成后关闭管道
	close(inChan)
}

// 从inChan读取数据,计算判断是否为素数,如果是则打印
func readData(inChan chan int, exitChan chan bool)  {
	//fmt.Println(time.Now() , " new goroutine")
	for {
		value ,ok := <-inChan
		if !ok {
			// 如果读不到,表示inChan内的数据已经取完了
			break
		}
		// 读取到的数,计算判断是否为素数
		if isPrieme(value){
			fmt.Println("prime = ", value)
		}
	}
	// 如果读取不到数据,表这个协程已经完成。
	exitChan<- true

}

func init(){
	// 设置可用处理器个数
	cpuNum := runtime.NumCPU()
	runtime.GOMAXPROCS(cpuNum-1)
	fmt.Println("cpuNum=",cpuNum)
}

func main(){
	fmt.Println("hello")

	// 一个用于保存待处理数据的管道
	var inChan chan int

	// 用与标记判断协程是否完成的管道
	var exitChan chan bool

	// 启动协程的数量
	var gorutNum int
	inChan = make(chan int, 200)
	exitChan = make(chan bool, 5)
	gorutNum = 5

	// 启动一个协程用于输入待处理的数据
	go writeData(inChan)

	// 启动多个协程用于处理数据
	for i:=0;i<gorutNum;i++ {
		go readData(inChan,exitChan)
	}

	// 阻塞主线程,等下协程的完成
	for {
		v,ok := <- exitChan
		if ok {
			fmt.Println(v)
			break
		}
	}
	fmt.Println("Done!")

}  

## 输出结果

 .....省略部分输出
prime =  139
prime =  149
prime =  151
prime =  157
prime =  163
prime =  167
prime =  173
prime =  179
prime =  181
prime =  191
prime =  193
prime =  197
prime =  199
true
Done!
prime =  2
prime =  3
prime =  17  

背景知识

  • 管道是线程安全的,也就是多协程同时操作一个协程,结果都是我们预期的效果。而golang中常用的内置数据结构,变量,切片,map都不是线程安全的。

  • 线程安全如何理解呢? 即当多个线程访问某个方法时,不管你通过怎样的调用方式或者说这些线程如何交替的执行,我们在主程序中不需要去做任何的同步,这个类的结果行为都是我们设想的正确行为,那么我们就可以说这个类时线程安全的。如果一段代码可以保证多个线程访问的时候正确操作共享数据,那么它是线程安全的

文章来源:智云一二三科技

文章标题:golang goroutine与channel入门练习题一

文章地址:https://www.zhihuclub.com/86302.shtml

关于作者: 智云科技

热门文章

发表评论

您的电子邮箱地址不会被公开。

网站地图