2011-12-12 47 views
0

我需要创建5个线程并将ArrayList与每个线程关联。我有另一个线程将从队列中读取值(逐个)并将该消息推送到与每个线程关联的 ArrayList我之前创建的线程。然后该线程应该从ArrayList中读取值并开始执行。我怎样才能做到这一点?在c中使用ArrayList的线程#

+4

你试过了什么?什么导致你详细设计? – BrokenGlass

+1

为什么使用ArrayList而不是队列? –

+0

对于大多数情况来说,让线程池管理活动线程的数量会更好。我会建议重新考虑你的方法,创建固定数量的显式线程是最好的方法。 –

回答

1

您可以使用Monitor类来同步您的线程。这是一个使用五个不同的锁和队列的示例,根据您的意见,每个线程都有一个锁。

使用锁来保护在两个不同线程之间共享的数据是很重要的。只有持有锁的线程才能访问数据。

其自己的个人对象上的工作线程锁(在同步阵列中),并且,具有锁,然后调用Monitor.Wait,这将释放锁。

主线程可能已经试图锁定该线程的同步对象,或将很快,这并不重要,因为它不会访问该线程的队列中,直到它确实有锁。然后排队消息是安全的。 Monitor.Pulse调用唤醒等待工作者线程,但工作人员停留在Monitor.Wait调用中,直到主线程释放锁(通过脱离锁(){}代码块)。

当Monitor.Wait返回给工作人员,锁定将被重新获得。

你不能总是假定线程会以相同的速率进行脉冲和唤醒,这就是为什么我在工作线程中有额外的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); 
       } 
      } 
     } 
    } 
} 
+0

感谢您的回复。你的帖子(帮助过的例子)帮了我很多 – json

1

因为分段线程(线程#6)将写入其他五个将读取的地方,所以不能使用不同步的数组列表。使用BlockingCollection是您的任务的不错选择。

创建并初始化5个BlockingCollection<T>对象的数组,并通过每个线程其集合的索引通过参数对象在数组中。五个“工作者”线程中的每一个都应当在初始化时传递的索引处的阻塞集合上调用Take(),并且执行他们需要执行的任何操作。工作包线程应该使用Add来为每个线程添加指定的值。

+0

你能解释一个例子吗?我是新线程 – json

1

我知道这并不直接回答你所问的,但我只是想知道这个想法是否可能更适合你想要做的事情。

而不是让每个线程一个ArrayList,使主队列中的线程安全队列System.Collections.Concurrent.ConcurrentQueue,并给每个线程对它的引用。然后,您不需要另一个线程将工作交给工作线程。

每个工作线程可以检查队列,看看是否有任何工作在等待。如果是这样,它抓住它,并处理。如果没有,线程再次检查前会休眠一段时间。

如果特定线程需要处理的值特定类型的(这就是你的其他线程是什么管理)这将无法正常工作,但它应该是合理的跨工人池基本负载分担。

+0

感谢您的意见。使用单线程读取主队列的原因是我需要控制消息流。这就是我使用单线程从队列中读取消息并将该消息添加到列表或数组列表的原因,以便与之关联的线程可以处理该消息。 – json

+0

我是线程新手。可以使用示例对其进行解释 – json

+0

可以在此处查看示例[ConcurrentQueue](http://msdn.microsoft.com/zh-cn/library/dd267265.aspx)。滚动到底部 – Ruzzie