channel,work_pool and select are finished

main
Your Name 2024-07-08 17:05:12 +08:00
parent dd9b607ebe
commit 0aae887404
6 changed files with 187 additions and 0 deletions

View File

@ -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:
//默认操作
}

View File

@ -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)
}

15
Concurrency/select.go Normal file
View File

@ -0,0 +1,15 @@
package main
import "fmt"
func main() {
//第一次1select选择一个能执行的即 ch<-i,把1放入通道第二次不能放入取出第三次再放入第四次再取出
ch := make(chan int, 1)
for i := 1; i <= 10; i++ {
select {
case x := <-ch:
fmt.Println(x)
case ch <- i:
}
}
}

35
Concurrency/work_pool.go Normal file
View File

@ -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
}
}

View File

@ -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()
}