自学内容网 自学内容网

Go 不可重复协程安全队列

代码实现

package dataStruct

import (
"errors"
"sync"
)

// GenericQueue 是一个支持泛型的不可重复队列,具有最大长度限制
// T 是泛型参数
type GenericQueue[T comparable] struct {
items   map[T]struct{} // 使用 map 来存储元素
order   []T            // 使用切片来记录元素的顺序
lock    sync.RWMutex   // 读写锁,保证并发安全
maxSize int            // 最大队列长度
}

// NewGenericQueue 创建一个新的泛型队列,并指定最大长度
func NewGenericQueue[T comparable](maxSize int) *GenericQueue[T] {
return &GenericQueue[T]{
items:   make(map[T]struct{}), // 初始化 items map
order:   []T{},                // 初始化 order 切片
maxSize: maxSize,              // 设置最大长度
}
}

// Add 添加元素到队列
// 如果队列已满,默认移除最旧的元素来腾出空间
func (q *GenericQueue[T]) Add(item T) error {
q.lock.Lock()         // 加写锁,防止并发修改
defer q.lock.Unlock() // 解锁

// 判断元素是否已经存在
if _, exists := q.items[item]; exists {
return errors.New("item already exists in the queue")
}

// 如果队列已满,移除最旧的元素
if len(q.order) >= q.maxSize {
return errors.New("Out of length Queue ")
}

// 将元素添加到 map 中,标记该元素已存在
q.items[item] = struct{}{}
// 将元素添加到队列顺序中
q.order = append(q.order, item)
return nil
}

// Remove 删除队列中的指定元素
// 如果元素不存在,则返回错误
func (q *GenericQueue[T]) Remove(item T) error {
q.lock.Lock()         // 加写锁,防止并发修改
defer q.lock.Unlock() // 解锁

// 判断元素是否存在
if _, exists := q.items[item]; !exists {
return errors.New("item not found in the queue")
}

// 从 map 中删除该元素
delete(q.items, item)

// 从顺序切片中删除该元素
for i, v := range q.order {
if v == item {
q.order = append(q.order[:i], q.order[i+1:]...) // 删除指定位置的元素
break
}
}
return nil
}

// Update 修改队列中的元素
// 如果元素不存在,则返回错误
func (q *GenericQueue[T]) Update(oldItem, newItem T) error {
q.lock.Lock()         // 加写锁,防止并发修改
defer q.lock.Unlock() // 解锁

// 判断 oldItem 是否存在
if _, exists := q.items[oldItem]; !exists {
return errors.New("old item not found in the queue")
}

// 判断 newItem 是否已存在
if _, exists := q.items[newItem]; exists {
return errors.New("new item already exists in the queue")
}

// 从 map 中删除 oldItem,并添加 newItem
delete(q.items, oldItem)
q.items[newItem] = struct{}{}

// 更新顺序切片中的 oldItem 为 newItem
for i, v := range q.order {
if v == oldItem {
q.order[i] = newItem
break
}
}
return nil
}

// Contains 查询队列中是否存在指定元素
func (q *GenericQueue[T]) Contains(item T) bool {
q.lock.RLock()         // 加读锁,防止并发修改
defer q.lock.RUnlock() // 解锁
_, exists := q.items[item]
return exists
}

// Traverse 遍历队列中的元素
func (q *GenericQueue[T]) Traverse() []T {
q.lock.RLock()         // 加读锁,防止并发修改
defer q.lock.RUnlock() // 解锁
// 返回元素的副本,防止并发问题
result := make([]T, len(q.order))
copy(result, q.order)
return result
}

// Iterator 返回一个可以用于 for range 的通道
func (q *GenericQueue[T]) Iterator() <-chan T {
ch := make(chan T)
go func() {
q.lock.RLock()         // 加读锁,防止并发修改
defer q.lock.RUnlock() // 解锁
defer close(ch)        // 关闭通道
for _, item := range q.order {
ch <- item
}
}()
return ch
}

介绍

1. 支持泛型

  • 队列支持泛型参数 T,因此可以存储任何类型的元素,只要该类型是 comparable(可比较的)。这意味着你可以使用这个队列来存储数字、字符串、结构体等类型的数据。

2. 不可重复

  • 队列内部通过 map 来存储元素,因此它自动确保元素的唯一性。也就是说,队列中不会有重复的元素。

3. 顺序存储

  • 使用切片 order 来记录元素的顺序,保证在遍历时元素的顺序是加入队列时的顺序。

4. 并发安全

  • 队列实现了并发控制,使用了 sync.RWMutex 读写锁来保证在多线程环境下的安全操作。多个 goroutine 可以并发地读取队列,或者一个 goroutine 可以安全地修改队列。

5. 常见操作

  • 添加元素(Add): 如果元素已经存在,则无法再次添加;如果队列已满,返回 Out of length Queue 错误,不会自动移除最旧元素
  • 删除元素(Remove): 可以删除队列中的某个元素。
  • 更新元素(Update): 可以将队列中的某个元素更新为新的元素,前提是新元素不存在。
  • 检查元素是否存在(Contains): 查询队列中是否包含某个元素。
  • 遍历队列(Traverse): 返回队列中所有元素的副本,供遍历使用。
  • 支持 for range 遍历: 通过 Iterator 方法,队列可以返回一个只读通道,可以直接在 for range 循环中使用。

6. 适用场景

  • 适用于需要按顺序处理且确保元素唯一的场景,例如任务队列、事件队列等。
  • 适用于并发环境,确保多个操作的安全性。

示例用法:

 

type Ta struct {
Name string
}

func main() {
impl := test.XueTestingImpl
impl.StartTest()

// 示例:创建一个支持整数的泛型队列
queue := dataStruct.NewGenericQueue[Ta](1024)
queue.Add(Ta{Name: "xzm"})
queue.Add(Ta{Name: "yyds"})
queue.Add(Ta{Name: "id"})

//修改
queue.Update(Ta{Name: "id"}, Ta{Name: "ids"})

//遍历
for ta := range queue.Iterator() {
fmt.Println(ta)
}

//查找
contains := queue.Contains(Ta{
Name: "yyds",
})

//删除
queue.Remove(Ta{
Name: "yyds",
})

fmt.Println(contains)

fmt.Println(queue)
fmt.Println(queue.Traverse())
impl.EndTest()
}


原文地址:https://blog.csdn.net/qq_52160611/article/details/145330782

免责声明:本站文章内容转载自网络资源,如侵犯了原著者的合法权益,可联系本站删除。更多内容请关注自学内容网(zxcms.com)!