2011-12-12 45 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