当前位置: 首页 > 工具软件 > ticker > 使用案例 >

Golang停止ticker断续器

班宏毅
2023-12-01

1.原代码如下

package main

import (
	"fmt"
	"time"
)

func main()  {
	intchan := make(chan int,1)
	ticker := time.NewTicker(time.Second)
	go func() {
		for  range ticker.C{ //每隔1s执行一次
			select {
			case intchan <- 1:
			case intchan <- 2:
			case intchan <- 3:
			}
		}
		fmt.Println("End.[sender]")
	}()

	var sum int
	for e:= range intchan{
		fmt.Printf("received:%v\n",e)
		sum += e
		if sum>=5{ 
			fmt.Printf("got:%v\n",sum)
			break
		}
	}
	fmt.Println("end.[receiver]")
}
  • 输出结果
    received:3
    received:2
    got:5
    end.[receiver]
    
  • 上述程序中,发送方会用断续器ticker每隔1s向intchan通道发送一个范围为[1,3]的伪随机数,这个发送操作并不会主动停止。接收方会一致累加接到的数,直到其和大于5停止。
  • 运行多次,End.[sender]始终无法打印出来

2.修改代码:在接收方暂停断续器ticker.stop

  • 在接收方加入ticker.Stop()代码,暂停断续器,查看是否能打印输出End.[sender]
package main

import (
	"fmt"
	"time"
)

func main()  {
	intchan := make(chan int,1)
	ticker := time.NewTicker(time.Second)
	go func() {
		for range ticker.C{
			select {
			case intchan <- 1:
			case intchan <- 2:
			case intchan <- 3:
			}
		}
		fmt.Println("End.[sender]")
	}()

	var sum int
	for e:= range intchan{
		fmt.Printf("received:%v\n",e)
		sum += e
		if sum>=5{
			fmt.Printf("got:%v\n",sum)
			ticker.Stop()
			break
		}
	}
	//time.Sleep(time.Second*2) 
	// 测试用,当主goroutine休眠了1s仍然无法输出End.[sender]
	fmt.Println("end.[receiver]")
}
  • 当和大于5时,暂停断续器,仍然无法打印输出End.[sender],即使主goroutine休眠1s
  • 解释:ticker的stop方法,该方法会停止计时,意味着不会向定时器的管道中写入事件,但管道并不会关闭。管道只有在使用完成后,声明周期结束后才会自动释放。
  • 即使停止了断续器,循环卡在循环range ticker.C,无法继续向下执行,所以无法打出End.[sender]

3.修改代码:添加一个stopchan管道

  • 添加一个stopchan管道,当主goroutine中sum大于等于5时,满足条件,向stopchan中传入数据。因为stopchan原先无数据,在select中无法执行该case,处于阻塞状态,当得到数据后,便会执行该case,执行其中代码
package main

import (
	"fmt"
	"time"
)

func main()  {
	intchan := make(chan int,1)
	stopchan := make(chan bool)
	ticker := time.NewTicker(time.Second)
	go func() {
		for  range ticker.C{
			select {
			case intchan<-1:
			case intchan<-2:
			case intchan<-3:
			case stop:=<-stopchan:
				if stop{
					ticker.Stop()
					fmt.Println("End.[sender]")
				}
			}
		}
		fmt.Println("End.[sender]")
	}()

	var sum int
	for e:= range intchan{
		fmt.Printf("received:%v\n",e)
		sum += e
		if sum>=5{
			fmt.Printf("got:%v\n",sum)
			stopchan <- true
			break
		}
	}
	fmt.Println("end.[receiver]")
}
  • 输出结果
received:1
received:3
received:2
got:6
End.[sender]
end.[receiver]
 类似资料: