我的问题是如何安排每个间隔N运行独立的非阻塞函数。
我最初的方法是在select语句中使用go通道以非阻塞方式接收值,并在每个函数中使用time.Sleep(N)
来安排调用。
在下面的代码段中,这仅适用于第一次运行;但是,在第一次通话后,它会反复拨打computeY()
而不尊重time.Sleep()
来电。
package main
import (
"fmt"
"time"
)
var (
x string = ""
y string = ""
)
func computeY(c chan string) {
time.Sleep(10 * time.Second)
fmt.Println("I'm in Y")
y = "this is Y value"
c <- y
}
func computeX(c chan string) {
time.Sleep(1 * time.Second)
x = "this is X value"
c <- x
}
func main() {
xC := make(chan string)
yC := make(chan string)
for {
go computeX(xC)
go computeY(yC)
select {
case x := <-xC:
fmt.Println(fmt.Sprintf("X: %v, Y: %v", x, y))
case y := <-yC:
fmt.Println(fmt.Sprintf("X: %v, Y: %v", x, y))
}
}
}
答案 0 :(得分:2)
在循环的每次迭代中,您都在调用computeX
和computeY
。
由于computeX
需要1,因此for
循环每秒迭代一次,yC
得到一个值的额外时间。
这意味着您在go computeY
,t=0s
,t=1s
等处运行t=2s
....
第一个终止于t=10s
,第二个终止于t=11s
,等等......
如果您想确保一次只安排一个computeX
和computeY
,则需要将主页更改为以下内容:
go computeX(xC)
go computeY(yC)
for {
select {
case x = <-xC:
fmt.Printf("Finished computeX: X: %v, Y: %v\n", x, y)
go computeX(xC)
case y = <-yC:
fmt.Printf("Finished computeY: X: %v, Y: %v\n", x, y)
go computeY(yC)
}
}
有关您的代码的其他一些注意事项:
x
和y
是全球性的,已在computeX
和computeY
x
和y
fmt.Println(fmt.Sprintf("..."))
只是fmt.Printf("...\n")
""
,这是默认值答案 1 :(得分:0)
虽然@ Marc的回答解释了您的代码问题,并说明了如何修复它,但我会尝试为您提供有关调度功能的一些模式。
模式1:time.Ticker
Ticker拥有一个提供`ticks&#39;每隔一段时间。
示例:
func Schedule(interval time.Duration,f func()) {
t:=time.NewTimer(interval)
go func() {
for {
<-t.C
f()
}
}()
}
模式2:time.AfterFunc
AfterFunc等待持续时间过去,然后在自己的goroutine中调用f。它返回一个Timer,可用于使用Stop方法取消呼叫。
示例:
func Schedule(interval time.Duration,f func()) {
var wrap func()
wrap = func() {
f()
time.AfterFunc(wrap)
}
time.AfterFunc(f)
}
模式1更具可读性和表现力,而模式2在内存上更有效。