Thread
前段时间看了golang.并行的模块停下来了,正好这个学期上操作系统,而且前段时间的五子棋设计的时候需要网络通信。多线程就成了必要的东西的了。是时候看看线程了。
在没有设计多线程之前,我们的程序是step by step的!
大程序往往会由许许多多的小程序组成,例如,Web服务器需要处理从浏览器发来的请求,并回复HTML页面。每个请求就像一个小程序。 web服务器能同时处理多个请求,这就需要并行的技术了。
在java中要使一个类的几个示例多线程运行,则类需要继承自Runnable
类。然后用 Thread
类来创建进程。(当然还有其他的方式).
在Go中,用goroutines
和 channels
来支持并行.
Goroutines
对于goroutines
:
A goroutine is a function that is capable of running concurrently with other functions.
要新建一个goroutine
:
package main
import "fmt"
import "time"
func f(n int) {
for i := 0; i < 10; i++ {
fmt.Println(n, ":", i)
time.Sleep(time.Millisecond * 1000)
}
}
func main() {
go f(0)
var input string
fmt.Scanln(&input)
}
上面的代码中有两个goroutine
。第一个是个隐式的:main
函数本身。第二个是我们用go f(0)
创建的。
正常情况下,函数调用会执行完返回再进入下一行,但是有了goroutine
,会马上执行下一行,不用等到函数返回。
这么看来,go语言的goroutine
比java中的轻量了许多。也方便了不少。
channels
对于channels
:
Channels provide a way for two goroutines to communicate with one another and synchronize their execution.
package main
import (
"fmt"
"time"
)
func pinger(c chan string) {
for i := 0; ; i++ {
c <- "ping"
}
}
func printer(c chan string) {
for {
msg := <- c
fmt.Println(msg)
time.Sleep(time.Second * 1)
}
}
func main() {
var c chan string = make(chan string)
go pinger(c)
go printer(c)
var input string
fmt.Scanln(&input)
}
channal的声明就不说了,我们可以当c时一个容器,这里是string容器。 printer会输出c里的内容,而pinger书不断往容器里放入"ping"。当容器是空的时候,printer就会阻塞了.
对了,channel是可以有buffer大小的:make(chan int , 3)
.
select
这是channel
的switch。
func main() {
c1 := make(chan string)
c2 := make(chan string)
go func() {
for {
c1 <- "from 1"
time.Sleep(time.Second * 2)
}
}()
go func() {
for {
c2 <- "from 2"
time.Sleep(time.Second * 3)
}
}()
go func() {
for {
select {
case msg1 := <- c1:
fmt.Println(msg1)
case msg2 := <- c2:
fmt.Println(msg2)
}
}
}()
var input string
fmt.Scanln(&input)
}