package main
import (
"fmt"
"runtime"
)
func main(){
//获取当前系统CPU的数量
cpuNum := runtime.NumCPU()
fmt.Println("cpuNum=", cpuNum)
//可以自己设置使用多少个CPU
runtime.GOMAXPROCS(cpuNum - 1)
fmt.Println("ok")
}
不同goroutine之间如何通信:
使用了sync包:sync包提供了基本的同步基元,如互斥锁。大部分都是适用于低水平程序线程,高水平的同步使用channel通信更好一些。
代码改进:
缺点:
package main
import (
"fmt"
)
func main(){
//演示管道的使用
//创建一个可以存放3个int类型的管道
var intChan chan int
intChan = make(chan int, 3)
//看看channel是什么
fmt.Printf("intChan的值=%v intChan本身的地址=%p\n", intChan, &intChan)
//向管道写入数据
intChan<- 10
num := 211
intChan<- num
//看看管道的长度和容量;管道的容量分配内存时已经确定,不会动态增长
fmt.Printf("intChan的长度=%v 容量=%v \n", len(intChan), cap(intChan))
//从管道中取数据
var num2 int
num2 = <-intChan
fmt.Println("num2=", num2)
//观察管道的长度,容量
fmt.Printf("intChan的长度=%v 容量=%v \n", len(intChan), cap(intChan))
//在没有使用协程的情况下,若管道中的数据已经全部取出,再取就会报告 deadlock
}
package main
import (
"fmt"
)
func main(){
intChan := make(chan int, 3)
intChan<- 10
intChan<- 20
//关闭channel
close(intChan)
//此时不能在写入数据,但是可以读取
num := <- intChan
fmt.Println("num", num)
}
package main
import (
"fmt"
)
func main(){
intChan := make(chan int, 3)
intChan<- 10
intChan<- 20
//关闭channel
close(intChan)
//此时不能在写入数据,但是可以读取
num := <- intChan
fmt.Println("num", num)
//遍历管道
intChan2 := make(chan int, 20)
for i := 0; i < 20; i++{
intChan2<- i*2 //放入20个数据到channel中
}
//遍历管道不能使用普通for循环
/*在遍历时,没有关闭管道,会遍历输出,
但会出现fatal error: all goroutines are asleep - deadlock!*/
close(intChan2)
for v := range intChan2{
fmt.Println("v=", v)
}
}
package main
import (
"fmt"
)
func WriteData(intChan chan int){
for i := 1; i <= 50; i++{
intChan<- i
fmt.Println("写入数据", i)
}
close(intChan)
}
func ReadData(intChan chan int, exitChan chan bool){
for{
v, ok := <-intChan
if !ok{
break
}
fmt.Println("读取的数据", v)
}
exitChan<- true
close(exitChan)
}
func main(){
//创建两个协程
intChan := make(chan int, 50)
exitChan := make(chan bool, 1)
go WriteData(intChan)
go ReadData(intChan, exitChan)
for{
_, ok := <-exitChan
if !ok{
break
}
}
}
package main
import (
"fmt"
)
func putNum(intChan chan int){
for i := 1; i <= 8000; i++{
intChan<-i
}
close(intChan)
}
func primeNum(intChan chan int, primeChan chan int, exitChan chan bool){
for{
num, ok := <-intChan
if !ok{
break
}
var flag = true //假定为素数
//判断num是否为素数
for i := 2; i < num; i++{
if num % i == 0{
flag = false
break
}
}
if flag{
primeChan<- num
}
}
exitChan<- true
fmt.Println("有一个协程已经走完了")
}
//统计1-8000中的素数个数
func main(){
//声明管道
intChan := make(chan int, 1000)
primeChan := make(chan int, 4000) //放素数结果
exitChan := make(chan bool, 4) //标识退出的管道
//开启一个协程putNum,向 intChan中放1-8000个数
start := time.Now().Unix()
go putNum(intChan)
//开启4个协程primeNum,从intChan中取出数据,并判断是否为素数
//如果是,就将其放入primeChan管道中
for i := 0; i < 4; i++{
go primeNum(intChan, primeChan, exitChan)
}
//另开起一个协程,用于判断是否上述4个primeNum协程已经运行完
go func(){
for i := 0; i < 4; i++{
<-exitChan
}
end := time.Now().Unix()
fmt.Println("使用协程耗时=", end - start)
//当从exitChan中取出4个值后,说明primeNum协程已经全部结束
//此时可以关闭primeChan管道
close(primeChan)
}()
//遍历取出结果
for{
res, ok := <-primeChan
if !ok{
break
}
//将结果输出
fmt.Println("是素数的有:", res)
}
}
package main
imoprt (
"fmt"
)
func main(){
//管道可以只声明为只读 或者 只写
var intChan chan int //双向管道,可读可写
var intChan2 chan<- int //只能写
var intChan3 <-chan int //只能读
intChan2 = make(chan int, 2)
intChan3 = make(chan int, 5)
}
package main
import (
"fmt"
)
func main(){
//使用select可以解决从管道取数据的阻塞问题
intChan := make(chan int, 10)
for i := 0; i < 10; i++{
intChan<-i
}
stringChan := make(chan string, 5)
for i := 0; i< 5; i++{
stringChan<- "hello" + fmt.Sprintf("%d", i)
}
//传统的方法在遍历管道时,如果不关闭会阻塞导致 deadlock
//而在实际开发中,存在不好确定什么时候关闭管道
//使用select方式解决上述问题
//label:
for{
select{
case v := <-intChan:
fmt.Printf("从intChan读取的数据%d\n", v)
case v := <-stringChan:
fmt.Printf("从stringChan读取的数据%s\n", v)
default:
fmt.Printf("都取不到数据\n")
return
//break label
}
}
}
package main
import (
"fmt"
"time"
)
func sayHello(){
for i := 0; i < 10; i++{
time.Sleep(time.Second)
fmt.Println("hello,world")
}
}
func test(){
//这里使用 defer + recover 捕获错误
defer func(){
//捕获test抛出的panic
if err := recover(); err != nil{
fmt.Println("test()发生错误", err)
}
}()
//定义一个map
var myMap map[int]string
myMap[0] = "golang" //此处发生错误
}
func main(){
go sayHello()
go test()
time.Sleep(time.Second * 20)
}