Notice: A non well formed numeric value encountered in /var/www/myblog/public/wp-content/plugins/crayon-syntax-highlighter/crayon_formatter.class.php on line 118
Notice: A non well formed numeric value encountered in /var/www/myblog/public/wp-content/plugins/crayon-syntax-highlighter/crayon_formatter.class.php on line 119
如下
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 |
package main import ( "fmt" "time" ) // Bucket 令牌桶的抽象实例 type Bucket struct { // bucket 为桶队列, stopSignal 作为停止信号 bucket, stopSignal chan struct{} // 桶的令牌数 num int // 单位时间 duration time.Duration } // New 构造初始化 func New(num int, t time.Duration) *Bucket { b := &Bucket{ bucket: make(chan struct{}, num), stopSignal: make(chan struct{}), num: num, duration: t, } go b.run() return b } // run 启动函数 func (b *Bucket) run() { // 先初始化给塞满桶 for i := 0; i < b.num; i++ { b.bucket <- struct{}{} } // 再来个定时器 ticker := time.NewTicker(b.duration) defer ticker.Stop() defer close(b.bucket) FOR: for { select { case <-ticker.C: // 如果已经满了,为防止超限,还要等待一会儿 if len(b.bucket) == b.num { time.Sleep(b.duration) continue } // 我们需要补充桶的令牌数 count:=b.num-len(b.bucket) for i := 0; i < count; i++ { b.bucket <- struct{}{} } case <-b.stopSignal: break FOR } } } // Stop 发送停止信号 func (b *Bucket) Stop() { b.stopSignal <- struct{}{} } // Get 获取一个令牌,如果没拿到,返回 false func (b *Bucket) Get() bool { select { case <-b.bucket: return true default: return false } } func main() { // 初始化一秒钟 5 个令牌 b := New(5, time.Second) // 模拟 10 个人抢 for i := 0; i < 10; i++ { go func(i int) { for { time.Sleep(time.Second / 2) if !b.Get() { fmt.Printf("协程 %d没抢到\n", i) continue } fmt.Printf("协程 %d 抢到了\n", i) } }(i) } select {} } |
© 著作权归作者所有
文章评论(0)