2011-12-12 2 views
0

스레드 5 개를 만들고 각 스레드에 ArrayList을 연결해야합니다. 큐에서 값을 읽고 (하나씩) 또 다른 스레드가 있습니다.이 메시지를 각각 ArrayList 내가 이전에 만든 스레드. 그 스레드는 ArrayList에서 값을 읽고 실행을 시작해야합니다. 어떻게해야합니까?C에서 ArrayList가있는 스레드

+4

무엇을 시도 했습니까? 그리고 당신이 상세히 설명한 디자인으로 당신을 안내합니까? – BrokenGlass

+1

왜 배열이 아니라 배열 을 사용하고 있습니까? –

+0

대부분의 경우 스레드 풀이 활성 스레드 수를 관리하게하는 것이 훨씬 좋습니다. 나는 당신의 접근법을 재검토 할 것을 제안 할 것이고, 고정 된 수의 명시 적 쓰레드를 생성하는 것이 가장 좋은 접근 방법이다. –

답변

1

모니터 클래스를 사용하여 스레드를 동기화 할 수 있습니다. 다음은 주석에 따라 각 스레드에 하나씩 5 개의 잠금 및 대기열을 사용하는 예제입니다.

두 개의 서로 다른 스레드간에 공유되는 모든 데이터를 잠그는 것이 중요합니다. 잠금 장치가있는 스레드 만 데이터에 액세스해야합니다.

작업 스레드는 (syncs 배열의) 자체 개체를 잠그고 잠긴 다음 Monitor.Wait를 호출하여 잠금을 해제합니다.

주 스레드가 이미 해당 스레드의 동기화 개체를 잠근려고했거나 곧 잠금을 가질 때까지 해당 스레드의 큐에 액세스 할 수 없기 때문에 중요하지 않습니다. 그런 다음 메시지를 대기열에 보관하는 것이 안전합니다. Monitor.Pulse 호출은 대기중인 작업자 스레드를 깨우지 만 주 스레드가 lock() {} 코드 블록에서 빠져 나올 때까지 작업자는 Monitor.Wait 호출에 멈춰 있습니다.

모니터. 잠깐만 요원에게 돌아 가면 자물쇠가 다시 채취됩니다.

항상 스레드가 펄스를 발생시키고 동일한 속도로 작동한다고 가정 할 수는 없습니다. 따라서 주 스레드가 몇 번 신호를 보낸 경우를 처리하기 위해 작업자 스레드에서 여분의 루프가 발생합니다 작업자가 실제로 처리하기 전에 여러 메시지가 처리되었습니다.

이 예제는 훨씬 단순화되어 있습니다. 예를 들어 작업자를 종료하는 방법에 대해서는 다루지 않지만 시작하기 전에 몇 가지 아이디어를 제공해야합니다.

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을 사용하면 작업에 적합한 선택입니다.

다섯 개의 BlockingCollection<T> 개체 배열을 만들고 초기화하고 매개 변수 개체를 통해 각 스레드에 해당 컬렉션의 인덱스를 배열에 전달합니다. 5 개의 "작업자"스레드 각각은 초기화시 전달 된 인덱스에서 블로킹 콜렉션의 Take()에 대한 호출을 반복해야하며 수행해야 할 작업을 모두 수행해야합니다. 작업 파싱 스레드는 Add을 사용하여 각 스레드에 지정된 값을 추가해야합니다.

+0

예제로 설명 할 수 있습니까? 스레딩을 처음 사용했습니다. – json

1

나는 이것이 당신이 묻고있는 것에 직접 대답하지 않는다는 것을 알고 있지만, 나는이 생각이 당신이하고자하는 것에 더 잘 들어 맞는 것인지 궁금해하고 있습니다.

각 스레드에 대해 ArrayList를 사용하는 대신 주 큐를 스레드 안전 큐 System.Collections.Concurrent.ConcurrentQueue으로 만들고 각 스레드에 대한 참조를 제공하십시오. 그런 다음 다른 스레드가 작업자 스레드로 작업을 전달할 필요가 없습니다.

각 작업 스레드는 큐를 확인하여 대기중인 작업이 있는지 확인할 수 있습니다. 그렇다면 그것을 잡아서 처리하는 것입니다. 그렇지 않은 경우 스레드는 다시 확인하기 전에 일정 기간 동안 잠자기 상태가됩니다.

특정 스레드가 특정 유형의 값 (그리고 다른 스레드가 관리하는 것)을 처리해야하는 경우에는 잘 작동하지 않지만 작업자 풀 전체에 대한 기본로드 공유에는 적합해야합니다.

+0

주석 주셔서 감사합니다. 주 큐에서 읽기 위해 단일 스레드를 사용하는 이유는 메시지 흐름을 제어해야하기 때문입니다. 그게 내가 하나의 스레드를 사용하여 큐에서 메시지를 읽고 해당 메시지를 목록이나 arraylist에 추가하여 그 스레드와 관련된 메시지를 처리 ​​할 수있게하는 이유입니다. – json

+0

나는 스레딩을 처음 사용합니다. 예제를 사용하여 설명 할 수 있습니까 – json

+0

예제는 [ConcurrentQueue] (http://msdn.microsoft.com/en-us/library/dd267265.aspx)에서 볼 수 있습니다. 아래쪽으로 스크롤 – Ruzzie

관련 문제