zoukankan      html  css  js  c++  java
  • 21天从Java转向Go之第九天——水滴石穿(gorutine和通道chan)

    goroutine

    CSP模型

    • (Coummunicating Sequential Process)通信顺序进程,CSP是一个并发模式,在不同的执行体(goroutine)之间传递值,但是变量本身局限于单一的执行体。
    • 当一个程序启动时,只有一个goroutine来调用main函数。称它为主goroutine。
    • 语法:在普通的函数或方法调用前加上go关键字前缀。go语句使函数在一个新创建的goroutine中调用。go语句本身的执行立即完成:
    f()   //调用f(),需要等待它返回
    go f() //新建一个调用f()的goroutine,调用完立即返回
    
    • 斐波那契数列demo
    package main
    
    import (
    	"fmt"
    	"time"
    )
    
    func main() {
    
    	go func() {
    		for {
    			for _, v := range `_/|\` {
    				fmt.Printf("\r%c", v)
    				time.Sleep(time.Second)
    			}
    		}
    	}()
    	fmt.Println(fib(50))
    }
    
    /**
    i index 0,1,2,3,...
    return v
    */
    func fib(i int) int {
    	if i < 2 {
    		return i
    	}
    	return fib(i-1) + fib(i-2)
    }
    

    通道chan

    • 通道是可以让一个goroutine发送特定值到另一个goroutine的通信机制。每个通道是一个具体类型的导管,叫做通道的元素类型。一个有int类型的通道写为chan int。make函数可以指定容量,创建一个带缓冲的通道。
    var ch = make(chan int)
    
    • 像map一样,通道是一个使用make函数创建的数据结构的引用。当复制或者作为参数传递到一个函数时,复制的是引用。这样调用者和被调用者都是引用同一份数据结构。通道的零值是nil。
    • 同种类型的通道==判断时,返回true
    • 通道两个操作:发送和接收
    ch <- x //发送语句
    <-ch //接收语句  丢弃结果
    y := <-ch //赋值语句中的接收表达式
    close(ch) //关闭通道
    
    • 无缓冲通道(同步通道)上的发送操作将会阻塞,直到另一个goroutine在对应的通道上执行接收操作,这时值传送完成,两个goroutine都可以继续执行。相反,如果接收方先执行接收操作,将阻塞直到另一个goroutine在同一个通道上发送一个值。
    • 单向通道 在函数参数上声明指定类型,传入实参时会隐式转换为参数要求的单向通道类型,但是反过来不行,不能由单向通道类型引用到底层同一个数据结构的chan的类型
    chan <- int  //只能发送类型的通道
    <-chan int  //只能接收int类型的通道
    
    • 缓冲通道,在make函数指定容量。缓冲通道上的发送操作在队列的尾部插入一个元素,接收操作从队列的头部移除一个元素。如果通道满了,会阻塞发送操作,通道空了,会阻塞接收操作。(类似于阻塞队列)

    • cap(ch) 获取通道的容量

    • len(ch) 获取通道元素的个数

    并行循环

    func loop(slices []int) {
    	result := make(chan int)
    	for _, v := range slices {
    		//v的值被所有的匿名函数值共享并且被后续的迭代更新。
    		//新的goroutine执行字面量函数,for循环可能已经更新了v,所以当这些goroutine读取f的值时,
    		//它们所看到的都是slice的最后一个元素。通过添加显示参数,可以确保当go语句执行的时候,使用f的当前值。
    		go func(v int) {   //捕获迭代变量 每次循环产生的函数,其记录的是循环变量的地址,所有循环产生的函数公用这一个值。
    			r := v * v
    			result <- r
    		}(v)
    	}
    	for _,v := range slices {
    		fmt.Println("v的平方:",v,<-result)
    	}
    }
    

    select case 后面用到时再回头看

  • 相关阅读:
    Android权限大全(链接地址整理)
    Android6.0运行时权限(基于RxPermission开源库)
    Android6.0机型上调用系统相机拍照返回的resultCode值始终等于0的问题
    使用AccessibilityService模拟点击事件失败的分析
    Android混淆打包配置总结
    okhttputils开源库的混淆配置(Eclipse)
    Android布局中的空格以及占一个汉字宽度的空格,实现不同汉字字数对齐
    java开发者大会:总结
    JAVA开发者大会:拍拍贷MQ系统原理与应用
    消息总线真的能保证幂等?
  • 原文地址:https://www.cnblogs.com/perkins/p/15629203.html
Copyright © 2011-2022 走看看