goroutine引出

需要大量计算的场景,比如需要统计 1-20000之间的素数。
思路分析:
1、传统方法:循环判断各个数是不是素数(判断除以 2到n-1,能否被整除),很耗费时间🔨
2、使用并发或者并行的方式,将任务分发给多个goroutine去完成

并发从宏观上看是多个线程在同时执行,微观角度是线程来回切换执行的(比如:一次下载多集电视剧)
迅雷下载
image.png

并发和并行

并发:多线程程序在单核cpu上运行。轮询来回切换线程(0.0几毫秒间隔)
并行:多线程程序在多核cpu上运行。
image.png
image.png

go协程和go主线程

go主线程(线程、进程),一个go线程上可以起多个协程(理论上起上万个协程没有问题)
协程(goroutine)是轻量级线程(编译器做优化)。
协程特点

  1. 有独立的栈空间
  2. 共享程序堆空间
  3. 调度由用户控制,开启、关闭等(主线程不由用户控制)
  4. 轻量级线程

image.png

协程案例

image.png
import “time”
func Sleep(d Duration)
Sleep阻塞当前go程至少d代表的时间段。d<=0时,Sleep会立刻返回。

代码

  1. // 协程 goroutinie 案例
  2. package main
  3. import (
  4. "fmt"
  5. "strconv"
  6. "time"
  7. )
  8. /*
  9. 主线程开启一个 goroutine 该协程每隔1秒输出 “hello goroutine”
  10. 主线程每隔1秒输出 “hello golang” 输出10次后退出程序
  11. 主线程和 goroutine 同时执行
  12. */
  13. // 编写函数
  14. func test() {
  15. for i := 1; i <= 2; i++ {
  16. fmt.Println("test() hello goroutine: " + strconv.Itoa(i))
  17. time.Sleep(time.Second)
  18. }
  19. }
  20. func main() {
  21. // test() // 执行完 test() 函数之后才会继续执行下面的程序
  22. go test() // 开启一个协程: goroutine (相当于是异步执行)
  23. for i := 1; i <= 5; i++ {
  24. fmt.Println("main() hello golang: " + strconv.Itoa(i))
  25. time.Sleep(time.Second)
  26. }
  27. }

执行效果

image.png

主线程和协程执行流程图

image.png

总结

  1. 主线程是一个物理线程,直接作用在cpu上的。是重量级的,非常耗费cpu资源。
  2. 协程从主线程开启的,是轻量级的线程,是逻辑态。对资源消耗相对小。
  3. Golang的协程机制是重要的特点,可以轻松的开启上万个协程。其它编程语言的并发机制是一般基于线程的,开启过多的线程,资源耗费大,这里就突显Golang在并发上的优势了