github.com/bruceshao/lockfree@v1.1.3-0.20230816090528-e89824c0a6e9/example/complex/main.go (about) 1 /* 2 * Copyright (C) THL A29 Limited, a Tencent company. All rights reserved. 3 * 4 * SPDX-License-Identifier: Apache-2.0 5 * 6 */ 7 8 package main 9 10 import ( 11 "fmt" 12 "github.com/bruceshao/lockfree" 13 "math/rand" 14 "sync" 15 "sync/atomic" 16 "time" 17 ) 18 19 func main() { 20 fmt.Println("========== start write by discard ==========") 21 writeByDiscard() 22 fmt.Println("========== complete write by discard ==========") 23 fmt.Println("========== start write by cursor ==========") 24 writeByCursor() 25 fmt.Println("========== complete write by cursor ==========") 26 } 27 28 func writeByDiscard() { 29 var counter = uint64(0) 30 // 写入超时,如何使用 31 eh := &fixedSleepEventHandler[uint64]{ 32 sm: time.Millisecond * 10, 33 } 34 disruptor := lockfree.NewLockfree[uint64](2, eh, lockfree.NewSleepBlockStrategy(time.Microsecond)) 35 disruptor.Start() 36 producer := disruptor.Producer() 37 // 假设有100个写g 38 var wg sync.WaitGroup 39 for i := 0; i < 10; i++ { 40 wg.Add(1) 41 go func() { 42 for j := 0; j < 10; j++ { 43 v := atomic.AddUint64(&counter, 1) 44 ww := producer.WriteWindow() 45 if ww <= 0 { 46 // 表示无法写入,丢弃 47 fmt.Println("discard ", v) 48 continue 49 } 50 // 表示可以写入,写入即可 51 err := producer.Write(v) 52 if err != nil { 53 panic(err) 54 } 55 fmt.Println("write ", v) 56 } 57 wg.Done() 58 }() 59 } 60 wg.Wait() 61 time.Sleep(3 * time.Second) 62 disruptor.Close() 63 } 64 65 func writeByCursor() { 66 var counter = uint64(0) 67 // 写入超时,如何使用 68 eh := &randomSleepEventHandler[uint64]{} 69 disruptor := lockfree.NewLockfree[uint64](2, eh, lockfree.NewSleepBlockStrategy(time.Microsecond)) 70 disruptor.Start() 71 producer := disruptor.Producer() 72 // 假设有100个写g 73 var wg sync.WaitGroup 74 for i := 0; i < 10; i++ { 75 wg.Add(1) 76 go func() { 77 for j := 0; j < 10; j++ { 78 v := atomic.AddUint64(&counter, 1) 79 wc, exist, err := producer.WriteTimeout(v, time.Millisecond) 80 if err != nil { 81 return 82 } 83 if !exist { 84 // 重复写入1次,写入不成功则丢弃重新写其他的 85 if ok, _ := producer.WriteByCursor(v, wc); ok { 86 continue 87 } 88 fmt.Println("discard ", v) 89 // 重新生成值,一直等待写入 90 v = atomic.AddUint64(&counter, 1) 91 for { 92 if ok, _ := producer.WriteByCursor(v, wc); ok { 93 fmt.Println("write ", v, " with x times") 94 break 95 } 96 // 写入不成功则休眠,防止CPU暴增 97 time.Sleep(100 * time.Microsecond) 98 } 99 } else { 100 fmt.Println("write ", v, " with 1 time") 101 } 102 } 103 wg.Done() 104 }() 105 } 106 wg.Wait() 107 time.Sleep(3 * time.Second) 108 disruptor.Close() 109 } 110 111 112 type fixedSleepEventHandler[T uint64] struct { 113 sm time.Duration 114 } 115 116 func (h *fixedSleepEventHandler[T]) OnEvent(v uint64) { 117 time.Sleep(h.sm) 118 fmt.Println("consumer ", v) 119 } 120 121 type randomSleepEventHandler[T uint64] struct { 122 count int32 123 } 124 125 func (h *randomSleepEventHandler[T]) OnEvent(v uint64) { 126 // 每次处理都会进行随机休眠,可以导致消费端变慢 127 intn := rand.Intn(1000) 128 time.Sleep(time.Duration(intn * 1000)) 129 fmt.Println("consumer count ", atomic.AddInt32(&h.count, 1)) 130 }