您的位置:首页 > 编程语言 > Go语言

【Golang学习笔记】05

2018-01-22 22:15 411 查看

要点

goroutine

runtime.GOMAXPPROCS

Channel select

sync.mutex

init

多线程

goroutine

go + func

func task01()  {
for ;; {
fmt.Println("task01")
}
}

func task02()  {
for ;; {
fmt.Println("task02")
}
}

func main() {
go task01()
go task02()
time.Sleep(1 * time.Minute)
}
/*
task1和task2并发执行
……
task01
task01
task02
task01
task02
task01
task01
……
*/


goroutine的匿名写法

//匿名goroutine
go func() {
fmt.Printf("\n Task3Start TimeNow: ",time.Now())
time.Sleep(2 * time.Second)
fmt.Printf("\n Task3End TimeNow: ",time.Now())
}()


sync.WaitGroup

阻塞线程,可以阻塞住主线程使其等待子线程结束

wg.Add(1),wg.Done(wg.Add(-1)),wg.Wait()当wg不为0时阻塞住线程

func task1()  {
fmt.Printf("\n Task1Start TimeNow: ",time.Now())
time.Sleep(1 * time.Second)  // 睡眠一秒
fmt.Printf("\n Task1End TimeNow: ",time.Now())
wg.Done()
}

func task2()  {
fmt.Printf("\n Task2Start TimeNow: ",time.Now())
time.Sleep(2 * time.Second)
fmt.Printf("\n Task2End TimeNow: ",time.Now())
wg.Done()
}

func main()  {
wg.Add(3)
fmt.Printf("\n CurTime: ",time.Now())
go task1()
go task2()

//匿名goroutine
go func() {//task3
fmt.Printf("\n Task3Start TimeNow: ",time.Now())
time.Sleep(2 * time.Second)
fmt.Printf("\n Task3End TimeNow: ",time.Now())
wg.Done()
}()

wg.Wait()
fmt.Printf("\n End CurTime: ",time.Now())
}

/*
task1 + task2 + task的阻塞时间是 1 + 2 + 2 = 5s,在使用goroutine后只耗费了2s
CurTime: %!(EXTRA time.Time=2018-01-22 21:31:19.405001 +0800 CST m=+0.005000301)
Task3Start TimeNow: %!(EXTRA time.Time=2018-01-22 21:31:19.4210019 +0800 CST m=+0.021001201)
Task1Start TimeNow: %!(EXTRA time.Time=2018-01-22 21:31:19.4210019 +0800 CST m=+0.021001201)
Task2Start TimeNow: %!(EXTRA time.Time=2018-01-22 21:31:19.4210019 +0800 CST m=+0.021001201)
Task1End TimeNow: %!(EXTRA time.Time=2018-01-22 21:31:20.4210591 +0800 CST m=+1.021058401)
Task3End TimeNow: %!(EXTRA time.Time=2018-01-22 21:31:21.4211163 +0800 CST m=+2.021115601)
Task2End TimeNow: %!(EXTRA time.Time=2018-01-22 21:31:21.4211163 +0800 CST m=+2.021115601)
End CurTime: %!(EXTRA time.Time=2018-01-22 21:31:21.4211163 +0800 CST m=+2.021115601)
*/


runtime.GOMAXPROCS

设置当前goroutine可使用的cpu最大数量, runtime.NumCPU() 此机器的cpu数量

func count()  {
x := 0
for i := 0; i < math.MaxInt32 ; i++ {
x ++
}
//  fmt.Println(x)
}

func task1(n int)  {
for i := 0; i < n; i++ {
count()
}
}

func task2(n int)  {
var wg sync.WaitGroup
for i := 0; i < n; i++ {
wg.Add(1)
go func() {
count()
wg.Done()
}()
}
wg.Wait()
}

func main() {
n := 5
start := time.Now().Second()
task1(n)
fmt.Printf("单线程共耗费时间: %v 秒 \n", time.Now().Second() - start)

for i := 1; i <= runtime.NumCPU(); i ++ {
start := time.Now().Second()
runtime.GOMAXPROCS(i)  //设置goroutine可使用的最大cpu数量 runtime.NumCPU() 此机器的cpu数量
task2(n)
fmt.Printf("Cpu使用数量:%v, 共耗费时间: %v 秒 \n", i, time.Now().Second() - start)
}
}

/*
单线程共耗费时间: 4 秒
Cpu使用数量:1, 共耗费时间: 4 秒
Cpu使用数量:2, 共耗费时间: 2 秒
Cpu使用数量:3, 共耗费时间: 2 秒
Cpu使用数量:4, 共耗费时间: 1 秒
Cpu使用数量:5, 共耗费时间: 1 秒
Cpu使用数量:6, 共耗费时间: 1 秒
Cpu使用数量:7, 共耗费时间: 1 秒
Cpu使用数量:8, 共耗费时间: 1 秒
*/


通道channel 阻塞线程

func main() {
event := make(chan struct{})

go func() {
time.Sleep(3 * time.Second)
close(event)
}()

<- event
fmt.Println("End")
}
//当子线程close(event)后,程序才会结束


close()

func main() {
a,b := make(chan int), make(chan int, 5)        // 默认为0  先进先出
b <- 1
b <- 2
b <- 3
fmt.Printf("a.len = %v  a.cap = %v \n", len(a), cap(a))  // a.len = 0  a.cap = 0
fmt.Printf("b.len = %v  b.cap = %v \n", len(b), cap(b))  // b.len = 3  b.cap = 5

close(b)    //如果channel被关闭了,就不可以往里放值,但是可以取值,而且不会死锁
//b <- 4    panic: send on closed channel
<- b
<- b
q, ok := <- b
fmt.Println(q, ok) // 3 true
q, ok = <- b
fmt.Println(q, ok) // 0 false
}


单向channel

var b <-chan interface{} = make(chan interface{}, 5)        // 只能读
var c chan<- interface{} = make(chan interface{}, 5)        // 只能写


channel的遍历

func main() {
a := make(chan int, 3)
a <- 10
a <- 20
a <- 30
close(a) // 如果不加这个,循环的时候就会因为等待输出阻塞线程,导致死锁
for i := range a{
fmt.Println(i)
}
}




func main() {
lenth :=  len(a)
for i := 0; i < lenth; i++ {
fmt.Println(<-a)
}
}


定时器

func main() {
t := time.NewTicker(1 * time.Second)
for  {
select {
case <- t.C:
fmt.Println("End")
}
}
}


sync.Mutex

防止两个线程同时使用一个资源,需要对资源加锁

func main() {
var wg sync.WaitGroup
a := 1
b := 1
wg.Add(4)

var ml sync.Mutex
// 不加锁

go func() {
for i := 0; i < 5000; i++ {
b += 1
}
wg.Done()
}()
go func() {
for i := 0; i < 5000; i++ {
b += 1
}
wg.Done()
}()

// 加锁
go func() {
ml.Lock()
for i := 0; i < 5000; i++ {
a += 1
}
wg.Done()
ml.Unlock()
}()
go func() {
ml.Lock()
for i := 0; i < 5000; i++ {
a += 1
}
wg.Done()
ml.Unlock()
}()

wg.Wait()

fmt.Println("不加锁后计算的值",b)
fmt.Println("加锁后计算的值",a)
}

//不加锁后计算的值 6842
//加锁后计算的值 10001


init

package LessonOther
import "fmt"

//init函数执行优先级高于main,
// 且可以有多个,
// 不可以被调用,
// 拼写必须是init
// 被其他包引用时也会调用
func init() {
fmt.Println("init1")
}

func init() {
fmt.Println("init2")
}

func init() {
fmt.Println("init3")
}

func Get()  {
fmt.Println("LessonOther -> Other.go -> Get 被调用")
}

package main

import "fmt"
import "../LessonOther"

func main() {
LessonOther.Get()
fmt.Println("main")
}

/*
init1
init2
init3
LessonOther -> Other.go -> Get 被调用
main
*/
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: