c#中带有数组列表的线程
本文关键字:列表 线程 数组 | 更新日期: 2023-09-27 18:17:46
我需要创建5个线程并将ArrayList
与每个线程关联。我有另一个线程将从队列中读取值(一个接一个)并将该消息推送到与我之前创建的每个线程相关联的数组列表。然后该线程应该从ArrayList中读取值并开始执行。我该怎么做呢?
您可以使用Monitor类来同步线程。下面是一个使用五种不同锁和队列的示例,每个线程一个,基于您的评论。
用锁保护两个不同线程之间共享的数据是很重要的。只有持有锁的线程才能访问数据。工作线程锁定自己的个人对象(在syncs数组中),并且拥有该锁,然后调用Monitor。等待,这将释放锁。
主线程可能已经尝试锁定该线程的同步对象,或者很快就会,这无关紧要,因为主线程在锁定之前无法访问该线程的队列。然后就可以安全地对消息进行排队了。监视器。脉冲调用唤醒等待的工作线程,但是工作线程仍然卡在它的监视器中。等待调用直到主线程释放锁(通过掉出lock(){}代码块)
当班长。Wait返回到worker,则锁将被重新获取。
你不能总是假设线程会以相同的速率脉冲和唤醒,这就是为什么我在工作线程中有额外的while循环,来处理主线程在工作线程实际唤醒处理它们之前已经用几个消息发出了几次信号的情况。
这个例子很简单——它不包括关闭工人,例如,但它应该给你一些开始的想法。
namespace ConsoleApplication1
{
using System;
using System.Collections.Generic;
using System.Threading;
internal class Program
{
private static readonly Queue<int>[] queues = new Queue<int>[5];
private static readonly object[] syncs = new object[5];
public static void Main(string[] args)
{
for (int i = 0; i < 5; i++)
{
queues[i] = new Queue<int>();
syncs[i] = new object();
var thread = new Thread(ThreadProc);
thread.Start(i);
}
var random = new Random();
while (true)
{
Thread.Sleep(1000);
int index = random.Next(queues.Length);
lock (syncs[index])
{
int message = random.Next(100);
queues[index].Enqueue(message);
Console.WriteLine("Sending message " + message + " to thread at " + index);
Monitor.Pulse(syncs[index]);
}
}
}
private static void ThreadProc(object data)
{
var index = (int)data;
lock (syncs[index])
{
while (true)
{
while (queues[index].Count == 0)
{
Monitor.Wait(syncs[index]);
}
int message = queues[index].Dequeue();
Console.WriteLine("Thread at " + index + " received message " + message);
}
}
}
}
}
您不能在没有同步的情况下使用数组列表,因为封装线程(线程#6)将写入其他五个将要读取的位置。对于您的任务,使用BlockingCollection
是一个很好的选择。
创建并初始化一个包含5个BlockingCollection<T>
对象的数组,并通过参数对象向每个线程传递其在数组中集合的索引。五个"工作"线程中的每一个都应该在初始化时传递的索引处循环调用阻塞集合上的Take()
,并执行它们需要执行的任何操作。工作打包线程应该使用Add
为每个线程添加指定的值。
我知道这并不能直接回答你的问题,但我只是想知道这个想法是否更适合你正在尝试做的事情。
与其为每个线程使用ArrayList,不如将主队列设置为线程安全的队列System.Collections.Concurrent。ConcurrentQueue,并给每个线程一个对它的引用。这样你就不需要另一个线程把工作交给你的工作线程了。
每个工作线程可以检查队列,看看是否有任何工作等待。如果是这样,它就会抓住它并进行处理。如果没有,线程会休眠一段时间,然后再进行检查。
如果特定的线程需要处理特定类型的值(这是你的另一个线程正在管理的),这将不能很好地工作,但对于跨工作池的基本负载共享来说,这应该是合理的。