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  }