【Golang学习笔记】05
2018-01-22 22:15
411 查看
要点
goroutineruntime.GOMAXPPROCS
Channel select
sync.mutex
init
多线程
goroutinego + 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 */
相关文章推荐
- golang学习笔记-json的处理
- 【Linux学习笔记】Linux_05_安装nginx,jdk,配jdk环境变量
- Go/Golang 语言学习笔记总结
- 二 git学习笔记05
- java学习笔记05--字符串 .
- (原创)c#学习笔记05--变量的更多内容01--类型转换03--使用Convert命令进行显式转焕
- go学习笔记:golang实现的反向代理
- (原创)c#学习笔记05--变量的更多内容02--复杂的类型变量01--枚举
- Effective C++学习笔记 条款05:了解C++默默编写并调用的哪些函数
- 05-java学习笔记-多线程2
- Golang学习笔记
- Golang学习笔记 方法和接口
- Scala学习笔记05--特质
- TGE学习笔记05 - 阴影
- java学习笔记05--字符串 .
- iOS学习笔记-145.网络05——NSURLConnection02_使用相关
- Python学习笔记05_函数
- C++ Standard Stl -- SGI STL源码学习笔记(05) stl_vector 与 一些问题的细化 1
- Java学习笔记05
- 学习笔记之05-printf和scanf函数