怪奇物语

怪奇物语

首页 新随笔 联系 管理

ConcurrentQueue和BlockingCollection的区别

区别

1. 阻塞行为(最核心区别)

  • ConcurrentQueue<T>:无阻塞机制

    它仅保证线程安全的队列操作,但不提供“阻塞”功能。

    • 当队列为空时,调用Dequeue()会直接抛出InvalidOperationException
      必须使用TryDequeue(out T)方法(返回bool表示是否成功),若失败需手动处理(如线程休眠、循环重试)。

    • 当队列非空时,入队(Enqueue(T))和出队(TryDequeue)操作均为非阻塞,直接执行。

  • BlockingCollection<T>:原生支持阻塞操作

    它的核心价值在于内置阻塞逻辑,无需手动处理线程等待:

    • 出队阻塞:调用Take()方法时,若集合为空,当前线程会阻塞,直到有元素可用(或集合被标记为“完成”)。

    • 入队阻塞:若为集合设置了容量上限(如new BlockingCollection<T>(boundedCapacity: 100)),当元素数量达到上限时,调用Add(T)阻塞,直到有元素被取出(腾出空间)。

    • 此外,还提供TryTake(out T, TimeSpan)TryAdd(T, TimeSpan)方法,支持“超时阻塞”(超过指定时间未成功则返回false),避免无限阻塞。

ConcurrentQueue<int> queue = new ConcurrentQueue<int>();


using System.Collections.Concurrent;
using System.Threading.Tasks;

class ConcurrentQueueExample
{
    private static readonly ConcurrentQueue<int> queue = new ConcurrentQueue<int>();
    private static volatile bool isProducingComplete = false;

    static async Task Main()
    {
        // 启动生产者任务
        var producerTask = Task.Run(() => Produce());

        // 启动消费者任务
        var consumerTask = Task.Run(() => Consume());

        // 等待生产者完成
        await producerTask;
        isProducingComplete = true; // 标记生产完成

        // 等待消费者完成
        await consumerTask;

        Console.WriteLine("所有任务已完成");
    }

    static void Produce()
    {
        for (int i = 0; i < 10; i++)
        {
            queue.Enqueue(i);
            Console.WriteLine($"生产者添加: {i}");
            Thread.Sleep(100); // 模拟生产耗时
        }
    }

    static void Consume()
    {
        // ♈♈♈♈♈♈♈♈♈♈♈♈♈♈♈♈♈
        while (!isProducingComplete || queue.Count > 0)
        {

            // ♈♈♈♈♈♈♈♈♈♈♈♈
            if (queue.TryDequeue(out int item))
            {
                Console.WriteLine($"消费者处理: {item}");
                Thread.Sleep(200); // 模拟消费耗时
            }
            else
            {
                // 队列为空时,短暂休眠避免CPU空转
                Thread.Sleep(50);
            }
        }
    }
}


BlockingCollection<int> collection = new BlockingCollection<int>();

using System.Collections.Concurrent;
using System.Threading.Tasks;
class BlockingCollectionExample
{
    private static readonly BlockingCollection<int> collection = new BlockingCollection<int>();
    static async Task Main()
    {
        // 启动生产者任务
        var producerTask = Task.Run(() => Produce());
        // 启动消费者任务
        var consumerTask = Task.Run(() => Consume());
        // 等待生产者完成
        await producerTask;
        ♈♈♈♈♈♈♈♈♈♈♈
        collection.CompleteAdding(); // 标记生产完成
        // 等待消费者完成
        await consumerTask;
        Console.WriteLine("所有任务已完成");
    }

    static void Produce()
    {
        for (int i = 0; i < 10; i++)
        {
            collection.Add(i);
            Console.WriteLine($"生产者添加: {i}");
            Thread.Sleep(100); // 模拟生产耗时
        }
    }

    static void Consume()
    {

        // ♈♈♈♈♈♈♈♈♈♈♈♈♈♈♈♈♈♈♈♈♈
        // 使用 GetConsumingEnumerable 自动处理阻塞和完成
        foreach (var item in collection.GetConsumingEnumerable())
        {
            Console.WriteLine($"消费者处理: {item}");
            Thread.Sleep(200); // 模拟消费耗时
        }
    }
}


posted on 2025-07-14 08:00  超级无敌美少男战士  阅读(43)  评论(0)    收藏  举报