我发现一个实现线程安全队列的旧代码。 我尝试使用ConcurrentQueue创建新的实现
旧代码
public class BoundedQueue<T> where T : class
{
private readonly Queue<T> _fixedSizeBuffer;
private object _bufferLock;
private int _limit;
public BoundedQueue(int limit)
{
_fixedSizeBuffer = new Queue<T>();
_limit = limit;
_bufferLock = new object();
for (int i = 0; i < _limit; i++)
{
_fixedSizeBuffer.Enqueue(null);
}
}
public void AddElementToBuffer(T element)
{
lock (_bufferLock)
{
_fixedSizeBuffer.Enqueue(element);
while (_fixedSizeBuffer.Count > _limit)
{
_fixedSizeBuffer.Dequeue();
}
}
}
public T GetElementAt(int index)
{
T element;
lock (_bufferLock)
{
element = _fixedSizeBuffer.ElementAt(_limit - index - 1);
}
return element;
}
}
我的新代码
public class FixedSizeConcurrentQueue<T> where T : class
{
private readonly ConcurrentQueue<T> _fixedSizeBuffer;
private int _maxSize;
public FixedSizeConcurrentQueue(int maxSize)
{
_maxSize = maxSize;
for (int i = 0; i < _maxSize; i++)
{
_fixedSizeBuffer.Enqueue(null);
}
}
public void AddElementToBuffer(T element)
{
_fixedSizeBuffer.Enqueue(element);
while (_fixedSizeBuffer.Count > _maxSize)
{
T item;
_fixedSizeBuffer.TryDequeue(out item);
}
}
public T GetElementAt(int index)
{
var element = _fixedSizeBuffer.ElementAt(_maxSize - index - 1);
return element;
}
}
我的问题是关于ElementAt()
函数还是我应该更好地称呼它TryGetElement()
。
在旧代码中,代码使用锁来同步不同的线程。
但是,在新代码中,我删除了它,因为我知道在有并发集合时使用锁是一种不好的做法。
因此,例如,如果由于队列为空而未找到索引,则会出现异常。
那么我应该用try catch包裹它吗?
请解释一下怎么做。
答案 0 :(得分:1)
您的maxsize
变量未跨线程同步,因此存在线程问题。此外,ConcurrentQueue
已经具有ElementAtOrDefault
函数,如果索引不存在,该函数将自动返回null
。
我将改为从ConcurrentQueue
本身继承。
public class FixedSizeConcurrentQueue<T> : ConcurrentQueue<T>
{
public int MaxSize { get; }
public FixedSizeConcurrentQueue(int maxSize)
{
MaxSize = maxSize;
}
public new void Enqueue(T obj)
{
base.Enqueue(obj);
while (base.Count > MaxSize)
{
T outObj;
base.TryDequeue(out outObj);
}
}
public T GetElementAt(int index)
{
return base.ElementAtOrDefault(index);;
}
}