管理多线程进程

本文关键字:进程 多线程 管理 | 更新日期: 2023-09-27 18:28:10

我有一项任务,我觉得很有挑战性,不知道如何开始。

问题是:

说:"我得到了一排随机的产品(包括a、B和C型)。"

p[A]、p[A],p[B]、p[C],p[C]、p[A]、p[B],p[B]。。。。

我将同时将这些产品发送到ProcessProduct(),但两个相同类型的产品不能一起处理。

以下是场景:

第一个p[A]将被处理,第二个p[A]将不得不等待第一个,第三个p[B]和第四个p[C]将立即被处理,而第五个p[C将不得不等待前一个。。。。

希望我的描述不要太混乱。如果有人能给我一些建议,我将不胜感激。非常感谢。

管理多线程进程

实现这一点的一种方法是将项目分组为三个不同的queus,每个类型一个队列。这会增加一些开销,但会让它变得容易得多。

这里有一些伪代码:

queueForTypeA=new queue()
queueForTypeB=new queue()
queueForTypeC=new queue()
foreach product in products
    if product is typeof A
        addLastInQueue(queueForTypeA, product)
    if product is typeof B
        addLastInQueue(queueForTypeB, product)
    if product is typeof C
        addLastInQueue(queueForTypeC, product)

然后,您可以分别处理每个队列,而不必担心一次处理2个相同类型的队列。

然而,此解决方案的扩展性不太好,如果您添加另一种类型的产品,则需要更改代码,这并不是最佳的。

因此,另一种选择是列出您正在处理的类型,然后每当您希望处理新产品时,您都会重新访问队列中的第一个项目,如果产品类型在productTypesBeingProcessed-列表中,则跳过行,选择下一个。

按类型对产品列表进行分组,然后并行处理每组。

已编辑

这是一个示例(如果产品列表是静态的):

sealed class Product
{
    public string Type
    {
        get;
        set;
    }
}
sealed class ProductProcessor
{
    public void StartProcessing(IEnumerable<Product> products)
    {
        foreach (var group in products.GroupBy(x => x.Type))
            Task.Factory.StartNew(() => ProcessProducts(group));
    }
    private void ProcessProducts(IEnumerable<Product> products)
    {
        foreach (Product product in products)
            ProcessProduct(product);
    }
    private void ProcessProduct(Product product)
    {
    }
}

这是要处理的动态产品队列的另一个示例(我没有运行代码,将其作为一种伪代码读取):

sealed class ProductProcessor
{
    public void Process(Product product)
    {
        lock (_queues)
        {
            if (_queues.ContainsKey(product.Type))
                _queues[product.Type].Enqueue(product);
            else
            {
                ConcurrentQueue<Product> queue = new ConcurrentQueue<Product>();
                queue.Enqueue(product);
                _queues.Add(product.Type, queue);
                WaitCallback action = delegate(object state)
                {
                    Product productToProcess;
                    while (queue.TryDequeue(out productToProcess))
                    {
                        ProcessProduct(productToProcess);
                    }
                    lock (_queues) _queues.Remove(product.Type);
                };
                ThreadPool.QueueUserWorkItem(action);
            }
        }
    }
    private Dictionary<string, ConcurrentQueue<Product>> _queues
        = new Dictionary<string, ConcurrentQueue<Product>>();
    private void ProcessProduct(Product product)
    {
    }
}

附言:您可以使用ConcurrentDictionary来代替锁。

使用生产者-消费者队列的数组,按产品类型进行索引。每个队列中只挂起一个线程,因此对每个产品类型依次调用ProcessProduct()。

我们只需为每种类型使用一个队列。然后每个队列一次只能有一个作业。所以您可以在每个队列的线程上使用。

我甚至看不出这里有什么问题?你在要求什么?代码示例?功能?

因为你似乎拘泥于概念,但大部分似乎都在这里。关键是每个队列只影响一个线程(如果不需要直接使用线程,则影响作业)