一、线程(geroutine)
1.线程使用
package main
import (
"fmt"
"runtime"
"time"
)
func geroutine(i int) {
fmt.Printf("[%d]geroutine is called.\n", i)
}
func main() {
runtime.GOMAXPROCS(6)
for i := 0; i < 10; i++ {
go geroutine(i)
}
time.Sleep(time.Second * 3)
}
输出结果:
[1]geroutine is called.
[9]geroutine is called.
[3]geroutine is called.
[0]geroutine is called.
[6]geroutine is called.
[4]geroutine is called.
[5]geroutine is called.
[8]geroutine is called.
[7]geroutine is called.
[2]geroutine is called.
2.等待线程结束WaitGroup
package main
import (
"fmt"
"runtime"
"sync"
"time"
)
var wg sync.WaitGroup
func geroutine(i int) {
defer wg.Done()
fmt.Printf("[%d]geroutine is called.\n", i)
time.Sleep(time.Second * 3)
}
func main() {
runtime.GOMAXPROCS(6)
for i := 0; i < 10; i++ {
wg.Add(1)
go geroutine(i)
}
//等待所有协程结束后退出
wg.Wait()
}
3.通知geroutine退出[context]
package main
import (
"context"
"fmt"
"sync"
"time"
)
var wg sync.WaitGroup
func main() {
ctx, cancle := context.WithCancel(context.Background())
//开启一个线程
wg.Add(1)
go func(ctx context.Context) {
defer wg.Done()
EXIT:
for {
fmt.Println("geroutine is called.")
time.Sleep(time.Second * 3)
select {
case <-ctx.Done():
break EXIT
default:
}
}
}(ctx)
time.Sleep(time.Second * 10)
cancle() //10s后通知子线程退出
//等待所有协程结束后退出
wg.Wait()
}
二、通道(channel)
1.定义
//通道必须经过make初始化才能使用
func main() {
var c chan int
fmt.Println(c) //<nil>
}
2.初始化
func main() {
var c chan int
fmt.Println(c) //<nil>
c = make(chan int) //不带缓冲区通道的初始化
c = make(chan int, 16) //带缓冲区通道的初始化
fmt.Println(c) //0xc000118000
}
3.通道的操作
package main
import (
"fmt"
"sync"
)
func main() {
var ch = make(chan int, 10)
var wg sync.WaitGroup
for i := 0; i < 10; i++ {
wg.Add(1)
go func() {
defer wg.Done()
//接收 从通道接收数据
x := <-ch
fmt.Println(x)
}()
}
//发送 将数据放入通道
//循环写通道:for v := range ch
for v := 0; v < 10; v++ {
ch <- v * v //数据:索引的平方
}
wg.Wait()
close(ch) //关闭通道
}
输出信息:
49
25
36
64
81
0
1
4
9
16
4.单向通道
func main() {
//接收通道,不能发送
ch1 := make(<-chan int, 10)
x := <-ch1
fmt.Println(x)
//发送通道,不能接收
ch2 := make(chan<- int, 10)
ch2 <- 1
}
5.关键字select
func main() {
ch := make(chan int, 5)
/*
select
1.哪个分支不阻塞执行哪个分支
2.所有可以执行的分支随机选择一个分支执行
*/
for i := 0; i < 10; i++ {
select {
case x := <-ch:
fmt.Println(x)
case ch <- i:
}
}
}
三、work pool
package main
import (
"fmt"
"sync"
"time"
)
var wg sync.WaitGroup
func worker(jobs <-chan int) {
defer wg.Done()
for x := range jobs {
time.Sleep(time.Second * 3)
fmt.Println("任务", x, "执行结果:", x*2)
}
}
func main() {
ch := make(chan int, 10)
//开启3个线程
for i := 0; i < 3; i++ {
wg.Add(1)
go worker(ch)
}
//执行10个任务
for i := 0; i < 10; i++ {
ch <- i
}
close(ch) //关闭后读取线程还能继续读取通道数据
wg.Wait()
}