我正在嘗試模擬一個程式,它需要在 N 秒內執行任務中的 X 任務并丟棄其他作業請求
當收到 on 的值時,我試圖timer在無限回圈中使用 with select <-timer.C,我正在繼續模擬任務,其中包含切片中的所有資料,這些資料受到保護maxLimit并timer再次將其重置為初始持續時間
這是代碼
type Pool struct {
// The maximum number of items allowed in pool
maxSize int
//the queue to hold the data
queue []interface{}
// time window for this pool
time time.Duration
//timer for the batch
timer *time.Timer
//channel
ch chan interface{}
}
func NewPool(maxSize int, t int32) *Pool {
p := &Pool{
maxSize: maxSize,
size: 0,
queue: make([]interface{}, maxSize),
time: time.Duration(t * int32(time.Second)),
timer: time.NewTimer(time.Duration(t) * time.Second),
ch: make(chan interface{}),
}
go p.Schedule()
return p
}
func (p *Pool) Add(ele interface{}) {
p.ch <- ele
}
func (p *Pool) Schedule() {
for {
select {
case <-p.timer.C:
fmt.Println("Time is over")
p.queue = make([]interface{}, 0)
p.timer.Reset(p.time)
p.flush()
case data := <-p.ch:
if len(p.queue) < p.maxSize {
fmt.Println("Addding")
p.queue = append(p.queue, data)
}
//p.flush()
if !p.timer.Stop() {
<-p.timer.C
}
p.queue = make([]interface{}, 0)
}
}
}
func (p *Pool) flush() {
for _, t := range p.queue {
fmt.Println("simulate some work here", t)
time.Sleep(500 * time.Millisecond)
}
}
func main() {
p := NewPool(5, 20)
for i := 0; i < 10000; i {
p.Add("xyz " fmt.Sprint(i))
}
}
但這沒有按預期作業我在這里遺漏了一些東西,你能指導我使用并發模式來滿足這個要求嗎,謝謝
uj5u.com熱心網友回復:
添加一些額外的輸出可以幫助您定位問題:
case data := <-p.ch:
fmt.Println("Got Data", len(p.queue), p.maxSize)
if len(p.queue) < p.maxSize {
p.queue = append(p.queue, data)
}
if !p.timer.Stop() {
fmt.Println("Draining")
<-p.timer.C
}
p.queue = make([]interface{}, 0)
}
使用該更改運行輸出為:
Got Data 5 5
Got Data 0 5
Addding
Draining
因此正在處理兩條訊息(第一條不會輸出Adding,因為len(p.queue)它是 5;這是因為您將其初始化為大小為 5 - make([]interface{}, maxSize))。考慮收到訊息時代碼在做什么:
- 處理
queue - 停止定時器
- 翻拍
queue
現在從檔案中獲取timer.Stop():
Stop 阻止 Timer 觸發。如果呼叫停止計時器,它回傳 true ,如果計時器已經過期或停止,則回傳 false 。
在第一次迭代中,它起作用了(計時器停止,如有必要,通道被耗盡)。但是,您在停止計時器后不會重置計時器,因此在第二次迭代時,當您呼叫時計時器已經停止p.timer.Stop()。這意味著Stop()它將回傳false(計時器已經停止!)并且您嘗試耗盡通道(但由于計時器已經停止,這將永遠阻塞)。
如何解決這個問題取決于你的目標;我懷疑你是想重置定時器?如果沒有,你可以這樣做:
if p.timer.C != nil && !p.timer.Stop() {
fmt.Println("Draining")
<-p.timer.C
}
p.timer.C = nil // Timer has been stopped (nil channel will block forever)
轉載請註明出處,本文鏈接:https://www.uj5u.com/qukuanlian/535730.html
標籤:去协程
