package main
import (
"fmt"
_ "time"
"sync"
)
// 需求:现在要计算 1-200 的各个数的阶乘,并且把各个数的阶乘放入到map中。
// 最后显示出来。要求使用goroutine完成
// 思路
// 1. 编写一个函数,来计算各个数的阶乘,并放入到 map中.
// 2. 我们启动的协程多个,统计的将结果放入到 map中
// 3. map 应该做出一个全局的.
var (
myMap = make(map[int]int, 10)
//声明一个全局的互斥锁
//lock 是一个全局的互斥锁,
//sync 是包: synchornized 同步
//Mutex : 是互斥
lock sync.Mutex
)
//使用协程+管道 ===>???
// test 函数就是计算 n!, 让将这个结果放入到 myMap
func test(n int) {
res := 1
for i := 1; i <= n; i++ {
res *= i
}
//这里我们将 res 放入到myMap
//加锁
lock.Lock()
myMap[n] = res //concurrent map writes?
//解锁
lock.Unlock()
}
func main() {
// 我们这里开启多个协程完成这个任务[200个]
for i := 1; i <= 20; i++ {
go test(i)
}
//休眠10秒钟【第二个问题 】
//time.Sleep(time.Second * 5)
//这里我们输出结果,变量这个结果
lock.Lock()
for i, v := range myMap {
fmt.Printf("map[%d]=%d\n", i, v)
}
lock.Unlock()
}
package main
import (
"fmt"
)
func main() {
//演示一下管道的使用
//1. 创建一个可以存放3个int类型的管道
var intChan chan int
intChan = make(chan int, 3)
//2. 看看intChan是什么
fmt.Printf("intChan 的值=%v intChan本身的地址=%p\n", intChan, &intChan)
//3. 向管道写入数据
intChan<- 10
num := 211
intChan<- num
intChan<- 50
// //如果从channel取出数据后,可以继续放入
<-intChan
intChan<- 98//注意点, 当我们给管写入数据时,不能超过其容量
//4. 看看管道的长度和cap(容量)
fmt.Printf("channel len= %v cap=%v \n", len(intChan), cap(intChan)) // 3, 3
//5. 从管道中读取数据
var num2 int
num2 = <-intChan
fmt.Println("num2=", num2)
fmt.Printf("channel len= %v cap=%v \n", len(intChan), cap(intChan)) // 2, 3
//6. 在没有使用协程的情况下,如果我们的管道数据已经全部取出,再取就会报告 deadlock
num3 := <-intChan
num4 := <-intChan
//num5 := <-intChan
fmt.Println("num3=", num3, "num4=", num4/*, "num5=", num5*/)
}
intChan 的值=0xc000086080 intChan本身的地址=0xc000080018
channel len= 3 cap=3
num2= 211
channel len= 2 cap=3
num3= 50 num4= 98
package main
import "fmt"
func main() {
var mapchan chan map[string]string
mapchan = make(chan map[string]string,10)
m1 := make(map[string]string,10)
m1["name"] = "阿凡达"
m1["age"] = "25"
m2 := make(map[string]string,10)
m2["name"] = "欧阳"
m2["age"] = "28"
mapchan <- m1
mapchan <- m2
fmt.Println(mapchan)
}
package main
import "fmt"
func main() {
intchan := make(chan int ,3)
intchan <- 100
intchan <- 200
close(intchan)
fmt.Println("11111111111")
n1 := <-intchan
fmt.Println(n1) //100
fmt.Println(<-intchan) //200
fmt.Println(<-intchan) //0
fmt.Println(<-intchan) //0
intchan <- 300 //panic: send on closed channel
}
package main
import (
"fmt"
"time"
)
//write Data
func writeData(intChan chan int) {
for i := 1; i <= 50; i++ {
//放入数据
intChan<- i //
fmt.Println("writeData ", i)
//time.Sleep(time.Second)
}
close(intChan) //关闭
}
//read data
func readData(intChan chan int, exitChan chan bool) {
for {
v, ok := <-intChan
if !ok {
break
}
time.Sleep(time.Second)
fmt.Printf("readData 读到数据=%v\n", v)
}
//readData 读取完数据后,即任务完成
exitChan<- true
close(exitChan)
}
func main() {
//创建两个管道
intChan := make(chan int, 10)
exitChan := make(chan bool, 1)
go writeData(intChan)
go readData(intChan, exitChan)
//time.Sleep(time.Second * 10)
for {
_, ok := <-exitChan
if !ok {
break
}
}
}
View Code
package main
import (
"fmt"
"time"
)
//向 intChan放入 1-8000个数
func putNum(intChan chan int) {
for i := 1; i <= 80000; i++ {
intChan<- i
}
//关闭intChan
close(intChan)
}
// 从 intChan取出数据,并判断是否为素数,如果是,就
// //放入到primeChan
func primeNum(intChan chan int, primeChan chan int, exitChan chan bool) {
//使用for 循环
// var num int
var flag bool //
for {
//time.Sleep(time.Millisecond * 10)
num, ok := <-intChan //intChan 取不到..
if !ok {
break
}
flag = true //假设是素数
//判断num是不是素数
for i := 2; i < num; i++ {
if num % i == 0 {//说明该num不是素数
flag = false
break
}
}
if flag {
//将这个数就放入到primeChan
primeChan<- num
}
}
fmt.Println("有一个primeNum 协程因为取不到数据,退出")
//这里我们还不能关闭 primeChan
//向 exitChan 写入true
exitChan<- true
}
func main() {
intChan := make(chan int , 1000)
primeChan := make(chan int, 20000)//放入结果
//标识退出的管道
exitChan := make(chan bool, 8) // 4个
start := time.Now().Unix()
//开启一个协程,向 intChan放入 1-8000个数
go putNum(intChan)
//开启4个协程,从 intChan取出数据,并判断是否为素数,如果是,就
//放入到primeChan
for i := 0; i < 8; i++ {
go primeNum(intChan, primeChan, exitChan)
}
//这里我们主线程,进行处理
//直接
go func(){
for i := 0; i < 8; i++ {
<-exitChan
}
end := time.Now().Unix()
fmt.Println("使用协程耗时=", end - start)
//当我们从exitChan 取出了4个结果,就可以放心的关闭 prprimeChan
close(primeChan)
}()
//遍历我们的 primeChan ,把结果取出
for {
_, ok := <-primeChan
if !ok{
break
}
//将结果输出
//fmt.Printf("素数=%d\n", res)
}
fmt.Println("main线程退出")
}
View Code
package main
import "fmt"
func send(ch chan<- int,exitchan chan struct{}){
for i :=0 ; i<10 ;i++{
ch<- i
}
close(ch)
var a struct{}
exitchan<- a
}
func recv(ch <-chan int,exitchan chan struct{}){
for{
v,ok:= <-ch
if !ok{
break
}
fmt.Println(v)
}
var a struct{}
exitchan<- a
}
func main() {
var ch chan int
ch = make(chan int,10)
exitchan := make(chan struct{},2)
go send(ch,exitchan)
go recv(ch,exitchan)
//var total = 0
//for _ = range exitchan{
// total++
// if total ==2{
// break
// }
//}
var total = 0
for{
_,ok:= <-exitchan
if !ok{
break
}
total++
if total ==2{
break
}
}
fmt.Println("结束")
}
View Code
package main
import "fmt"
func main() {
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)
}
for{
select{
case v:= <-intchan:
fmt.Printf("从intchan读取的数据%d\n",v)
case v := <-stringchan:
fmt.Printf("从stringchan读取的数据%d\n",v)
default:
fmt.Printf("都取不到了,不玩了")
return
}
}
}
View Code
package main
import (
"time"
"fmt"
)
func sayHello(){
for i:=0;i<10;i++{
//time.Sleep(time.Second)
fmt.Println("hello world")
}
}
func test(){
defer func(){
if err := recover();err!=nil{
fmt.Println("test() 发生错误",err)
}
}()
var myMap map[int]string
//myMap = make(map[int]string,6)
myMap[0] = "golang"
}
func main() {
go sayHello()
go test()
time.Sleep(time.Second*10)
}
sync:
sync案例
上图每次执行结果都不相同
通过加互斥锁