----------------------------------------- go 并发

// 注解:go 语言天生为程序并发所设计,可以说go的强项就是在cpu并发上的处理。
// go 语言层面就支持了并发。(不是一般高级语言的多线程并发,是系统级真实并发)
// go 语言通过安全的通道发送和接受数据以实现同步
// 一般情况下,一个普通的桌面计算机跑十几二十几个线程就有点负载过大了,但是同样的硬件设备go可以轻松上K。

----------------------------------------- goroutine

// 注解:go 并发设计的核心,goroutine在并发中起到的作用就是协程(CSP),但是它比线程更小。(协程=微线程)
// go 不支持后台协程,意思就是主程序退出,协程跟着一起退出
func newTask() {
for {
fmt.Println("new task ...")
time.Sleep(time.Second) // 休眠1s
}
} func main() {
go newTask() // 新建一个协程,新建一个任务 for {
fmt.Println("main ...")
time.Sleep(time.Second) // 休眠1s
}
}
// result :
// main...
// new task ...
// ....

----------------------------------------- gosched

// 注解:让出CPU时间片,让出当前 gorotine 的执行权限,
// 调度器安排其他等待任务运行,并在下次某个时候从该位置恢复执行。
func main() {
go func() {
for i := ; i < ; i++ {
fmt.Println("go")
}
}() for i := ; i < ; i++ {
fmt.Println("hello")
} // 这种情况,匿名函数未得到执行程序就结束了。
// 时间片案例演示代码,修改如下:
for i := .... {
runtime.Gosched()
fmt.Println("hello")
}
// 执行结果:
// go go ... hello ..
}

----------------------------------------- goexit

import "runtime"
// 注解:终止所在的协程 (所在的协程不是当前函数)
func test() {
defer fmt.Println("ccccc")
runtime.Goexit()
fmt.Println("dddd")
} func main() {
go func (){
fmt.Println("aaaa")
test()
fmt.Println("bbbb")
}
for {
} // result:
// aaaa cccc
}

----------------------------------------- gomaxProcs

// 注解:设置可以并行计算的 CPU 核数的最大值
import "runtime" func main() {
n := runtime.GOMAXProcs() //制定以1核运算
fmt.Println("n = ", n) for {
go fmt.Print()
fmt.Print()
} // 打印结果:11111.. 一大片, 00000...一大片
// 如果设置 GOMAXProcs(4) 为 4 核交叉效果更好
}

----------------------------------------- 资源争夺问题 channel

// 注解:channel 也是一种数据类型,同步
// 语法:channel <- value // 发送 value 数据到 channel
// <- channel // 接收并丢弃 // 案例:
// 全局变量,创建一个 channel
var ch = make(chan int) // 定义一个打印机,参数为字符串,按每个字符打印
func Printer(str string) {
for _, data := range str {
fmt.Printf("%c", data)
time.Sleep(time.Second)
}
fmt.Printf("\n")
} func person1() {
Printer("loong print")
ch <- // 给管道写数据
} func person2() {
<- ch // 从管道取数据,如果管道没有数据前他就会阻塞
Printer("make print")
} func main() {
// 新建 2 个协程,代表 2 个人,2 个人同时使用打印机
go person1()
go person2()
}
// 注解: 【认真看】
// 没有 channel 的情况
// 打印结果混乱,person1 打印一个h,person2 打印一个 w,交叉了。不符合我们的要求
// 增加 channel ,则在 <-ch 的地方进行了阻塞,通过进、出的方式融合这种解决这种并发互抢资源的问题。

----------------------------------------- channel 实现同步和数据交互

fun main() {
ch := make(chan string) defer fmt.Println("主协程也结束") go func() {
defer fmt.Println("子协程调用完毕。") for i := ; i < ; i++ {
fmt.Println("子协程 i=", i)
time.Sleep(time.Second)
} ch <- "我是子协程,工作完毕"
} str := <-ch // 没有数据前,阻塞
fmt.Println("str = ", str)
} // 注意:程序需求:主程序结束之前,能够完整执行匿名函数中的代码
// 使用 channel 配合完成

----------------------------------------- channel 无缓存&有缓存

c1 := make(chan int)         无缓冲
c2 := make(chan int,) 有缓冲
c1 < -
// 无缓冲:不仅仅是向 c1 通道放 1,
// 而是一直要等有别的协程 <-c1 接手了这个参数,那么c1<-1才会继续下去,要不然就一直阻塞着。
// 有缓冲: c2<-1 则不会阻塞,因为缓冲大小是1(其实是缓冲大小为0),
// 只有当放第二个值的时候,第一个还没被人拿走,这时候才会阻塞。 // 不需要再使用记得关闭channel close(c1)
// 判断管道是否关闭 if num, ok := <- c1; ok == true { // 关闭了 } ----------------------------------------- channel 单方向
var ch1 chan int // ch1 是一个正常的 channle,不是单向的
var ch2 chan<- float64 // ch2 是单向 channel,只用于写 float64 数据
var ch3 <-chan int // ch3 是单向 channel,只用于读取 int 数据 // * 管道的操作,一定要避免死锁的情况。

----------------------------------------- channel 应用

// 此案例可以应用很多场景,每写一个,则可以消耗一个
// 此通道只能写,不能读
func producer(out chan<- int) {
for i := ; i < ; i++ {
out <- i * i
} close(out)
} // 此通道只能读,不能写
func consumer(in <-chan int) {
for num := range in {
fmt.Println("num = ", num)
}
} func main() {
// 创建一个双向通道
ch := make(chan int) // 生产者,生产数字,写入 channel
// 开启一个协程
go producer(ch) // 消费者,从channel读取内容打印
consumer(ch)
}

----------------------------------------- Timer

import (
"time"
"fmt"
) func main() {
// 创建一个定时器,设置时间为2s,2s后,往time通道写内容
timer := time.NewTimer( * time.Second)
fmt.Println("当前时间:", time.Now()) // 2s后,往timer.C写数据,有数据后读取
t := <-time.C // channel 没有数据前后阻塞
fmt.Println("t = ", t)
}

----------------------------------------- select

// 注解:go语言提供了一个关键字 select,通过 select 可以监听 channel 上的数据流动
// 语法:(类似 switch)
select {
case <-chan:
// 如果channel 成功读到数据,则进入 case 块语句
case chan<- :
// 如果channel 成功写到数据,则进入 case 块语句
default:
// 如果上面都没有成功,则进入default处理流程
// 注意:慎用,很消耗 cpu
}

C#/JAVA 程序员转GO/GOLANG程序员笔记大全(DAY 06)的更多相关文章

  1. C#/JAVA 程序员转GO/GOLANG程序员笔记大全(DAY 05)

    ----------------------------------------- error 使用 (异常处理) // 语法 (普通错误) import "errors" fun ...

  2. C#/Java 程序员转GO/golang程序员笔记大全(day 01)

    前言: 整理一下学习 Go 语言的笔记,作为一名老程序,学习一名新的开发语言自然不需要像小白那样从 HelloWorld 看起. 简单整理一下 Go 的一些差异处,希望对大家学习 go 有点帮助,不正 ...

  3. C#/JAVA 程序员转GO/GOLANG程序员笔记大全(DAY 00)

    一.安装说明 https://studygolang.com/dl 二.环境变量 // 下载 *.msi 安装文件,部分环境变量默认配置好了. 其他配置如下描述 三.目录及项目层级关系 在系统环境变量 ...

  4. C#/JAVA 程序员转GO/GOLANG程序员笔记大全(DAY 04)

    -------------------- interface 接口 // 定义: type IHumaner interface { SayHi() // 接口中只能是方法声明,没有实现,没有数据字段 ...

  5. C#/JAVA 程序员转GO/GOLANG程序员笔记大全(DAY 03)

    go语言当中,没有 class 的概念,那么面向对象的编程思想如何展现呢,go语言中对结构体的使用 struct. package main import "fmt" type P ...

  6. C#/JAVA 程序员转GO/GOLANG程序员笔记大全(DAY 02)

    ------------------- 指针 go 保留的 c 语言指针的操作,同时增加了自动垃圾回收机制 var a = new(int) *a = // &a 内存地址 --------- ...

  7. PHP笔记——java程序员看懂PHP程序

    PHP笔记——java程序员看懂PHP程序   php是一种服务器端脚本语言,类型松散的语言. <?php   ?>       xml风格 <script language=”ph ...

  8. 使用 Java 开发兼容 IPv6 的网络应用程序

    根据现有 IPv4 地址的部署速度,剩余的地址将在 10 到 20 年被使用殆尽.因此网络逐渐从 IPv4 向 IPv6 转换是不可避免的,相应的各种网络应用程序都将支持 IPv6.对于 Java,从 ...

  9. StackOverflow程序员推荐:每个程序员都应读的30本书

    “如果能时光倒流,回到过去,作为一个开发人员,你可以告诉自己在职业生涯初期应该读一本,你会选择哪本书呢?我希望这个书单列表内容丰富,可以涵盖很多东西.” 很多程序员响应,他们在推荐时也写下自己的评语. ...

随机推荐

  1. Deep learning与Neural Network

    深度学习是机器学习研究中的一个新的领域,其动机在于建立.模拟人脑进行分析学习的神经网络,它模仿人脑的机制来解释数据,例如图像,声音和文本.深度学习是无监督学习的一种. 深度学习的概念源于人工神经网络的 ...

  2. linux mysql备份

    许多备份方案: http://blog.jobbole.com/14012/ 采用的: mysqldump ---user admin ---password=password mydatabase ...

  3. struts.xml 配置文件的主要元素

    1.package元素 作用: 在struts2的配置文件中引入了面向对象思想.分包管理,易于管理动作类,便于模块化开发动作类. 属性: name:包的名称.名称唯一. extends:一般情况下需要 ...

  4. CodeForces - 343C Read Time (二分+贪心)

    题意:有N个指针头,M个标记,用这N个针头扫描所有的标记,针头之间互不影响,求扫描完M个标记的最短时间 分析:二分搜答案,mid为时间限制,则只要所有的点在mid秒内被扫描到即可. 对于每个指针,若其 ...

  5. asp.net时间显示

    DateTime dt = DateTime.Now;//    Label1.Text = dt.ToString();//2005-11-5 13:21:25//    Label2.Text = ...

  6. docker swarm overlay stack 服务部署记录

    项目xxx(后端),xxx-ui前端(前后端分离的项目) 依赖mysql,elasticsearch.分别制作了四个镜像来做这件事.希望可以制作跨主机的部署,使用了swarm,以下是学习记录. 参考 ...

  7. akka消息传递

    消息传递 消息本身要求是什么?是否必须可以序列化?消息传递根据传递的要求严格程序依次分为三类,1.至多一次到达 至消息最多一次传递到目的端,消息可能会丢失,但不会重复2.至少一次到达 潜在可能存在多次 ...

  8. selenium+xpath 文本信息定位

    selenium中根据父子.兄弟.相邻节点定位的方法,很多人在实际应用中会遇到想定位的节点无法直接定位,需要通过附近节点来相对定位的问题,但从父节点定位子节点容易,从子节点定位父节点.定位一个节点的哥 ...

  9. java中hashSet原理

    转自: http://blog.csdn.net/guoweimelon/article/details/50804799 HashSet是JavaMap类型的集合类中最常使用的,本文基于Java1. ...

  10. Thinkphp5.0实战开发二------自动生成目录结构

    序言 ThinkPHP5.0 具备自动创建功能,可以用来自动生成需要的模块及目录结构和文件等,自动生成主要调用\think\Build 类库.ThinkPHP5.0中模块文件夹在application ...