go 泛型实现顺序队列

import "sync"

// 顺序队列
type SequentialQueue[T interface{}] struct {
	item []T
	lock sync.Mutex //加锁以便多线程使用
}

// 创建一个顺序队列
func NewSQueue[T interface{}]() *SequentialQueue[T] {
	return &SequentialQueue[T]{}
}

// 入队
func (s *SequentialQueue[T]) Put(value T) {
	s.lock.Lock()
	s.item = append(s.item, value)
	s.lock.Unlock()
}

// 出队
func (s *SequentialQueue[T]) Pop() (T, bool) {
	s.lock.Lock()
	var value T
	if s.IsEmpty() {
		return value, false
	}
	value = s.item[0]
	s.item = s.item[1:]
	s.lock.Unlock()
	return value, true
}

// 顺序队列的长度
func (s *SequentialQueue[T]) Len() int {
	return len(s.item)
}

// 判断队列是否为空
func (s *SequentialQueue[T]) IsEmpty() bool {
	return s.Len() == 0
}

这里我使用了空接口作为泛型类型,在go1.18之后空接口的定义是所有类型的集合,所以这个队列可以存放任意类型的数据。同时我对出队与入队加了锁,所以此队列在多线程环境下是线程安全的。使用注意需要go1.18以上版本。

测试:

单线程

func TestPut(t *testing.T) {
	squeue := queue.NewSQueue[string]()

	for i := 0; i < 10; i++ {
		squeue.Put(fmt.Sprint(i))
	}

	fmt.Println("队列长度:", squeue.Len())

	for {
		value, bl := squeue.Pop()
		if !bl {
			break
		}
		fmt.Print(value + " ")
	}
	fmt.Println()
	fmt.Println("队列运行结束,队列的长度是:", squeue.Len(), squeue.IsEmpty())
}

结果:

多线程

func TestThreadSqunen(t *testing.T) {
	squeue := queue.NewSQueue[string]()

	for i := 0; i < 20; i++ {
		squeue.Put(fmt.Sprint(i))
	}
	go printSqueue[string](squeue)
	go printSqueue[string](squeue)
	time.Sleep(5 * time.Second)
	fmt.Println()
	fmt.Println("队列运行结束,队列的长度是:", squeue.Len(), squeue.IsEmpty())
}

func printSqueue[T interface{}](s *queue.SequentialQueue[T]) {
	for {
		value, bl := s.Pop()
		if !bl {
			break
		}
		fmt.Print(fmt.Sprintf("%v ", value))
	}
}

结果:

可以看到多线程情况下队列是线程安全的。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值