From 0aae887404a11e13a13bf3c567aba87a19270c88 Mon Sep 17 00:00:00 2001 From: Your Name Date: Mon, 8 Jul 2024 17:05:12 +0800 Subject: [PATCH] channel,work_pool and select are finished --- Concurrency/{concurrency => Concurrency.log} | 16 +++++ Concurrency/channel_practice.go | 56 +++++++++++++++++ Concurrency/select.go | 15 +++++ Concurrency/work_pool.go | 35 +++++++++++ Concurrency/work_pool_practice.go | 65 ++++++++++++++++++++ reflector/{refelect => refelect.log} | 0 6 files changed, 187 insertions(+) rename Concurrency/{concurrency => Concurrency.log} (84%) create mode 100644 Concurrency/channel_practice.go create mode 100644 Concurrency/select.go create mode 100644 Concurrency/work_pool.go create mode 100644 Concurrency/work_pool_practice.go rename reflector/{refelect => refelect.log} (100%) diff --git a/Concurrency/concurrency b/Concurrency/Concurrency.log similarity index 84% rename from Concurrency/concurrency rename to Concurrency/Concurrency.log index e56e0b9..d697ad6 100644 --- a/Concurrency/concurrency +++ b/Concurrency/Concurrency.log @@ -50,3 +50,19 @@ M:N 复用/调度M的goroutine的到N个os线程 一个操作系统的线程对应多个用户态的goroutine 狗程序可以同时使用多个操作系统线程 goroutine和os线程时多对多的关系,即M:N + + +select多路复用 +Select 的使用方式类似于之前学到的 switch 语句,它也有一系列 case 分支和一个默认的分支。 +每个 case 分支会对应一个通道的通信(接收或发送)过程。select 会一直等待,直到其中的某个 case 的通信操作完成时,就会执行该 case 分支对应的语句。具体格式如下: + +select { +case <-ch1: + //... +case data := <-ch2: + //... +case ch3 <- 10: + //... +default: + //默认操作 +} \ No newline at end of file diff --git a/Concurrency/channel_practice.go b/Concurrency/channel_practice.go new file mode 100644 index 0000000..f638833 --- /dev/null +++ b/Concurrency/channel_practice.go @@ -0,0 +1,56 @@ +package main + +import ( + "fmt" + "sync" +) + +// channel练习 + +var WG sync.WaitGroup + +// 1.启动一个goroutine生成100个数字,发送到ch1 +func set100Num(ch1 chan<- int) { //在声明后添加符号类型表示单向通道 + defer WG.Done() + for i := 0; i < 100; i++ { + ch1 <- i + } + close(ch1) +} + +// 2.启动一个goroutine从ch1中取值,计算其平方,放到ch2中 +func get100Num(ch1 <-chan int, ch2 chan<- int) { + defer WG.Done() + for { + x, ok := <-ch1 + if !ok { + break + } + ch2 <- x * x + } + close(ch2) +} + +//3.在main函数中从ch2中取值,打印出来 + +func main() { + e := make(chan int, 50) + f := make(chan int, 100) + WG.Add(2) + go set100Num(e) + go get100Num(e, f) + WG.Wait() + for ret := range f { + fmt.Printf("通道中数字的平方是:%v\n", ret) + } + ch3 := make(chan int, 2) + ch3 <- 10 + ch3 <- 20 + <-ch3 + <-ch3 + close(ch3) //取完值后关闭通道 + t, ok := <-ch3 + //第三次仍能取到 + fmt.Println("第三此取出的值为", ok, t) + +} diff --git a/Concurrency/select.go b/Concurrency/select.go new file mode 100644 index 0000000..498de61 --- /dev/null +++ b/Concurrency/select.go @@ -0,0 +1,15 @@ +package main + +import "fmt" + +func main() { + //第一次1,select选择一个能执行的即 ch<-i,把1放入通道,第二次,不能放入,取出,第三次再放入,第四次再取出 + ch := make(chan int, 1) + for i := 1; i <= 10; i++ { + select { + case x := <-ch: + fmt.Println(x) + case ch <- i: + } + } +} diff --git a/Concurrency/work_pool.go b/Concurrency/work_pool.go new file mode 100644 index 0000000..3305944 --- /dev/null +++ b/Concurrency/work_pool.go @@ -0,0 +1,35 @@ +package main + +import ( + "fmt" + "time" +) + +func worker(id int, jobs <-chan int, results chan<- int) { + for j := range jobs { + fmt.Println("worker", id, "started job", j) + time.Sleep(time.Second) + fmt.Println("worker", id, "finished job", j) + results <- j * 2 + } +} + +// work_pool练习 +func main() { + jobs := make(chan int, 100) + results := make(chan int, 100) + //开启三个goroutine + for w := 1; w <= 3; w++ { + go worker(w, jobs, results) + } + //五个任务,0-5的数字放到jobs这个通道中 + for j := 1; j <= 5; j++ { + jobs <- j + } + //关闭job + close(jobs) + //把results这个通道中的数字,即jobs中的结果*2取出 + for a := 1; a <= 5; a++ { + <-results + } +} diff --git a/Concurrency/work_pool_practice.go b/Concurrency/work_pool_practice.go new file mode 100644 index 0000000..e3ecc16 --- /dev/null +++ b/Concurrency/work_pool_practice.go @@ -0,0 +1,65 @@ +package main + +import ( + "fmt" + "math/rand" + "sync" + "time" +) + +//使用 goroutine 和 channel 实现一个计算int64随机数各位数和的程序,例如生成随机数61345,计算其每个位数上的数字之和为19。 +//开启一个 goroutine 循环生成int64类型的随机数,发送到jobChan +//开启24个 goroutine 从jobChan中取出随机数计算各位数的和,将结果发送到resultChan +//主 goroutine 从resultChan取出结果并打印到终端输出 + +var w sync.WaitGroup + +type job struct { + value int64 +} +type Result struct { + job *job + sum int64 +} + +var jobChan = make(chan *job, 100) +var resultChan = make(chan *Result, 100) + +func producer(prod chan<- *job) <-chan *job { + defer w.Done() + for { + x := rand.Int63() + newJob := &job{value: x} + jobChan <- newJob + time.Sleep(time.Millisecond * 500) + } +} + +func consumer(con chan<- *Result, prod <-chan *job) { + defer w.Done() + for { + v := <-prod + sum := int64(0) + n := v.value + for n > 0 { + sum += n % 10 + n = n / 10 + } + newResult := &Result{job: v, sum: sum} + con <- newResult + } +} + +func main() { + w.Add(1) + go producer(jobChan) + w.Add(24) + for i := 0; i < 24; i++ { + go consumer(resultChan, jobChan) + } + for i := range resultChan { + fmt.Printf("随机数为:%d,加和为:%d\n", i.job.value, i.sum) + } + w.Wait() + +} diff --git a/reflector/refelect b/reflector/refelect.log similarity index 100% rename from reflector/refelect rename to reflector/refelect.log