多线程环境下的集合选择:BlockingCollection vs. ConcurrentBag,灵活应对线程安全数据操作

作者:微信公众号:【架构师老卢】
1-9 8:56
581

概述:在C#中,BlockingCollection和ConcurrentBag是用于多线程环境的集合类。BlockingCollection适用于生产者-消费者模型,提供阻塞等待的特性。ConcurrentBag适用于多线程环境下无序的元素插入和删除。根据具体需求,选择合适的集合类有助于实现线程安全的数据处理。

BlockingCollectionConcurrentBag是C#中用于多线程环境的集合类。BlockingCollection基于阻塞队列,适用于生产者-消费者模型,提供了对任务的安全访问。ConcurrentBag是一个无序的、线程安全的集合,适用于多线程环境下无序的元素插入和删除。

方法

  • BlockingCollection

    • Add(item):向集合中添加元素,如果集合已满则阻塞。
    • Take():从集合中取出元素,如果集合为空则阻塞。
  • ConcurrentBag

    • Add(item):向集合中添加元素,支持并发添加。
    • TryTake(out item):尝试从集合中取出元素。

步骤

  1. BlockingCollection

    • 创建BlockingCollection对象。
    • 使用Add方法添加元素。
    • 使用Take方法取出元素。
  2. ConcurrentBag

    • 创建ConcurrentBag对象。
    • 使用Add方法添加元素。
    • 使用TryTake方法尝试取出元素。

实例源代码

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

class Program
{
    static void Main()
    {
        // 使用BlockingCollection
        BlockingCollection<int> blockingCollection = new BlockingCollection<int>(boundedCapacity: 5);

        // 生产者
        Task.Run(() =>
        {
            for (int i = 0; i < 10; i++)
            {
                blockingCollection.Add(i);
                Console.WriteLine($"生产者添加: {i}");
                Thread.Sleep(100);
            }
            blockingCollection.CompleteAdding();
        });

        // 消费者
        Task.Run(() =>
        {
            foreach (var item in blockingCollection.GetConsumingEnumerable())
            {
                Console.WriteLine($"消费者取出: {item}");
                Thread.Sleep(200);
            }
        });

        // 使用ConcurrentBag
        ConcurrentBag<int> concurrentBag = new ConcurrentBag<int>();

        // 多线程并发添加元素
        Parallel.For(0, 10, i =>
        {
            concurrentBag.Add(i);
            Console.WriteLine($"添加元素: {i}");
            Thread.Sleep(100);
        });

        // 多线程并发尝试取出元素
        Parallel.For(0, 10, i =>
        {
            if (concurrentBag.TryTake(out var item))
            {
                Console.WriteLine($"尝试取出元素: {item}");
            }
            Thread.Sleep(200);
        });
    }
}

注意事项

  1. BlockingCollection适用场景:适用于生产者-消费者模型,需要阻塞等待的场景,例如任务处理队列。
  2. ConcurrentBag适用场景:适用于无序、并发添加和取出的场景,例如并行处理任务。

BlockingCollection适用于需要阻塞等待的生产者-消费者模型,提供了高度的灵活性。ConcurrentBag适用于多线程环境下无序的元素插入和删除场景,提供了更简单的接口。在选择时需根据具体场景的需求来决定使用哪个集合类。

阅读排行