关于golang利用channel和goroutine完成统计素数的思路

1. 需求

要求统计1-200000的数字中,哪些是素数?这个问题在本章开篇就提出来了,可以使用goroutine和channel来完成

2.分析思路

传统的方法,就是使用一个循环,循环的判断各个数是不是素数【ok】

使用并发/并行的方式,将统计素数的任务分配给多个(x个)goroutine去完成,完成任务时间短

分析思路图:

 代码实现:

package main
import (
	"fmt"
	"time"
)
// 需求:
// 要求统计1-200000的数字,哪些是素数?这个问题在本章开篇就提出了,现在我们有goroutine和channel的知识后,就可以完成了【测试数据:80000】
// 分析思路:
// 传统的方法,就是使用一个循环,循环的判断各个数是不是素数【ok】
// 使用并发/并行的方式,将统计素数的任务分配给多个(x个)goroutine去完成,完成任务时间短

// 1. 向intChan放入1-8000的数字
func putNum(intChan chan int) {
	for i := 1; i <= 20000; i++ {
		intChan <- i
	}
	// 关闭intChan
	close(intChan)
}

// 从intChan中取出数据,并判断是否为素数,如果是,就放入到primeChan
func primeNum1(intChan chan int, primeChan chan int, exitChan chan bool) {
	// 使用for循环
	var flag bool
	for {
		time.Sleep(time.Millisecond * 10)
		num, ok := <- intChan

		if !ok { //intChan取不到,且关闭了管道
			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("有一个prieNum 协程因为取不到数据,退出")
	// 这里我们还不能关闭primeChan
	// 向exitChan写入true
	exitChan <- true
}
func main() {
	var intChan chan int = make(chan int, 1000)
	var primeChan chan int = make(chan int,2000)
	// 标识退出的管道
	exitChan := make(chan bool,4)
	// 开启一个协程,向intChan放入 1-8000个数
	go putNum(intChan)
	// 开启4个协程,从 intChan中取出数据,并判断是否为素数,如果是就放入到primeChan
	for i := 0; i < 10000; i++ {
		go primeNum1(intChan,primeChan,exitChan)
	}
	// 这里我们主线程,进行处理
	go func() {
		for i := 0; i < 4; i++ {
			<-exitChan
		}
		// 当我们从exitChan中取出了4个结果,就可以放心的关闭primeChan
		close(primeChan)
	}()
	// 遍历我们的primeChan,把结果取出
	for {
		res, ok := <- primeChan
		if !ok {
			break
		}
		// 将结果取出
		fmt.Printf("素数=%d\n",res)
	}
	fmt.Println("main线程退出")
}

结论:使用go协程结合channel后,执行的速度,会大大 提高

go中可以轻松开启1万个协程

到此这篇关于golang利用channel和goroutine完成统计素数的文章就介绍到这了,更多相关golang统计素数内容请搜索我们以前的文章或继续浏览下面的相关文章希望大家以后多多支持我们!

(0)

相关推荐

  • golang实现基于channel的通用连接池详解

    前言 golang的channel除了goroutine通信之外还有很多其他的功能,本文将实现一种基于channel的通用连接池.下面话不多说了,来一起看看详细的介绍吧. 功能 * 连接池中连接类型为interface{},使得更加通用 * 链接的最大空闲时间,超时的链接将关闭丢弃,可避免空闲时链接自动失效问题 * 使用channel处理池中的链接,高效 何为通用? 连接池的实现不依赖具体的实例,而依赖某个接口,本文的连接池选用的是io.Closer接口,只要是实现了该接口的对象都可以被池管理.

  • GOLANG使用Context管理关联goroutine的方法

    一般一个业务很少不用到goroutine的,因为很多方法是需要等待的,例如http.Server.ListenAndServe这个就是等待的,除非关闭了Server或Listener,否则是不会返回的.除非是一个API服务器,否则肯定需要另外起goroutine发起其他的服务,而且对于API服务器来说,在http.Handler的处理函数中一般也需要起goroutine,如何管理这些goroutine,在GOLANG1.7提供context.Context. 先看一个简单的,如果启动两个goro

  • 解决Golang中goroutine执行速度的问题

    突然想到了之前一直没留意的for循环中开goroutine的执行顺序问题,就找了段代码试了试,试了几次后发现几个有意思的地方,我暂时没有精力往更深处挖掘,希望有golang大神能简单说一说这几个地方是怎么回事. 代码: package main import "fmt" func Count(ch chan int) { fmt.Println("Count doing") ch <- 1 fmt.Println("Counting") }

  • Golang优雅关闭channel的方法示例

    前言 最近使用go开发后端服务,服务关闭需要保证channel中的数据都被读取完,理由很简单,在收到系统的中断信号后,系统需要做收尾工作,保证channel的数据都要被处理掉,然后才可以关闭系统.但实现起来没那么简单,下面来一起看看详细的介绍吧. 关于Go channel设计和规范的批评: 在不能更改channel状态的情况下,没有简单普遍的方式来检查channel是否已经关闭了 关闭已经关闭的channel会导致panic,所以在closer(关闭者)不知道channel是否已经关闭的情况下去

  • golang中for循环遍历channel时需要注意的问题详解

    前言 for循环是Go语言唯一的循环结构,最近在做一个基于RabbitMQ的应用,由于官方的qos没有golang的版本,所以出了一点问题. 问题代码如下: _, ch, err := component.NewRabbitMQ() if err != nil { panic(err) } if err := ch.Qos(10, 0, true); err != nil { panic(err) } msgs, err := ch.Consume("push", "&quo

  • golang中单向channel的语法介绍

    本文主要给大家介绍的是关于golang单向channel语法的相关内容,分享出来供大家参考学习,下面话不多说,来一起看看详细的介绍: 今天闲来无事补充一下golang的语法知识,想起来看看context的用法,结果碰到了一个没见过的channel语法: // A Context carries a deadline, cancelation signal, and request-scoped values // across API boundaries. Its methods are sa

  • golang gin 框架 异步同步 goroutine 并发操作

    goroutine机制可以方便地实现异步处理 package main import ( "log" "time" "github.com/gin-gonic/gin" ) func main() { // 1.创建路由 // 默认使用了2个中间件Logger(), Recovery() r := gin.Default() // 1.异步 r.GET("/long_async", func(c *gin.Context) {

  • 关于golang利用channel和goroutine完成统计素数的思路

    1. 需求 要求统计1-200000的数字中,哪些是素数?这个问题在本章开篇就提出来了,可以使用goroutine和channel来完成 2.分析思路 传统的方法,就是使用一个循环,循环的判断各个数是不是素数[ok] 使用并发/并行的方式,将统计素数的任务分配给多个(x个)goroutine去完成,完成任务时间短 分析思路图:  代码实现: package main import ( "fmt" "time" ) // 需求: // 要求统计1-200000的数字,

  • 详解Golang中Channel的用法

    如果说goroutine是Go语言程序的并发体的话,那么channels则是它们之间的通信机制.一个channel是一个通信机制,它可以让一个goroutine通过它给另一个goroutine发送值信息. 1 创建channel 每个channel都有一个特殊的类型,也就是channels可发送数据的类型.一个可以发送int类型数据 的channel一般写为chan int.使用内置的make函数,如果第二个参数大于0,则表示创建一个带缓存的channel. ch := make(chan in

  • 使用Golang的channel交叉打印两个数组的操作

    Go的channel提供了强大的同步功能,那么如何使用channel交叉打印两个数组呢? 灰常简单,只需设置两个channel变量 数组1打印完一个值就用channel通知数组2,同理数组2打印完一个值用另一个channel通知数组1,即可实现同步 package main import "fmt" func main(){ ch1 :=make(chan int) ch2 :=make(chan string) str :=[5]string{"a","

  • Golang 语言控制并发 Goroutine的方法

    goroutine 是 Go语言中的轻量级线程实现,由 Go 运行时(runtime)管理.Go 程序会智能地将 goroutine 中的任务合理地分配给每个 CPU. 01介绍 Golang 语言的优势之一是天生支持并发,我们在 Golang 语言开发中,通常使用的并发控制方式主要有 Channel,WaitGroup 和 Context,本文我们主要介绍一下 Golang 语言中并发控制的这三种方式怎么使用?关于它们各自的详细介绍在之前的文章已经介绍过,感兴趣的读者朋友们可以按需翻阅. 02

  • Golang中channel的原理解读(推荐)

    数据结构 channel的数据结构在$GOROOT/src/runtime/chan.go文件下: type hchan struct { qcount uint // 当前队列中剩余元素个数 dataqsiz uint // 环形队列长度,即可以存放的元素个数 buf unsafe.Pointer // 环形队列指针 elemsize uint16 // 每个元素的大小 closed uint32 // 标记是否关闭 elemtype *_type // 元素类型 sendx uint //

  • golang 中 channel 的详细使用、使用注意事项及死锁问题解析

    目录 什么是channel管道 channel的基本使用 定义和声明 操作channel的3种方式 单向channel 带缓冲和不带缓冲的channel 不带缓冲区channel 带缓冲区channel 判断channel是否关闭 rangeandclose for读取channel select使用 channel的一些使用场景 1.作为goroutine的数据传输管道 2.同步的channel 3.异步的channel 4.channel超时处理 使用channel的注意事项及死锁分析 未初

  • Golang中Channel实战技巧与一些说明

    目录 Channel 的一些实战说明 关于 close Channel close Channel 的一些说明 v, ok := <-ch 判断是否 close 优雅判断是否 close 的封装 for-range 读取 Channel 数据 select 读写 Channel 数据 Channel 的读写超时机制[select + timeout] TryEnqueue 无阻塞写 Channel 数据 Channel 常见错误和根因分析 fatal error: all goroutines

  • Golang通道channel的源码分析

    目录 前言 channel基础结构 channel初始化 channel发送 channel接收 小结 前言 channel是golang中标志性的概念之一,很好很强大! channel(通道),顾名思义,是一种通道,一种用于并发环境中数据传递的通道.通常结合golang中另一重要概念goroutine(go协程)使用,使得在golang中的并发编程变得清晰简洁同时又高效强大. 今天尝试着读读golang对channel的实现源码,本文主要是自己个人对于Channel源码的学习笔记,需要的朋友可

  • Golang 利用反射对结构体优雅排序的操作方法

    最近开始实习,工作技术栈主要Python和Golang,目前的任务把Python模块重构为GO模块,然后出现了一个问题,就是要将一个结构体按结构体中各个字段进行排序,然后写入Redis,对于Pyhon来说for循环就能解决,但是对于Go语言来说,每一次排序都要写一个比较函数,写出来的代码太丑,非常长,代码结构是一致,只是比较字段不一样而已,个人无法接受啊,网上搜索也没搜索到合适解决方法,所以自己想了一个解决方法来优雅排序. 比较函数: func reflectCmp(i, j interface

  • Golang利用位运算实现为程序加速

    目录 前言 用位运算优化 其他奇淫巧技 总结 前言 最近在持续优化之前编写的 JSON 解析库 xjson,主要是两个方面的优化. 第一个是支持将一个 JSONObject 对象输出为 JSON 字符串. 这点在上个版本中只是利用自带的 Print 函数打印数据: func TestJson4(t *testing.T) { str := `{"people":{"name":{"first":"bob"}}}` first

随机推荐