C#의 Resource Pool (리소스 풀)

C# 언어를 활용하여 스레드를 통해 코드를 동시에 실행하고자 하는데, DB Connection과 같은 유한한 자원을 미리 생성해 놓고 활용하고자 합니다. 이때 사용할 리소스 풀로써 만든 클래스입니다.

class ResourcePool<T>
{
    private readonly ConcurrentBag<T> _items = new ConcurrentBag<T>();
    private ManualResetEvent _event = new ManualResetEvent(true);

    public ResourcePool(List<T> items) {
        var iter = items.GetEnumerator();

        while(iter.MoveNext())
        {
            _items.Add(iter.Current);
        }
    }

    public void Release(T item)
    {
        _items.Add(item);
        _event.Set();
    }

    public T Get()
    {
        T item;

        do
        {
            if (_items.IsEmpty)
            {
                _event.Reset();
                _event.WaitOne();
            }
        } while (!_items.TryTake(out item));
            
        return item;
    }
}

위의 ResourcePool은 generic 클래스로 어떤 객체 타입이든 리소스로써 담아두고 활용할 수 있습니다. 예를 들어, 아래와 같은 클래스로 말입니다.

class Resource
{
    public int v {
        get;
        set;
    }

    private int _useCount = 0;

    public Resource(int v)
    {
        this.v = v;
    }

        
    public void increaseUsingCount()
    {
        _useCount++;
    }

    public string toString()
    {
        return "V: " + v + " Count: " + _useCount;
    }
}

이 리소스 풀에 스레드에서 사용할 리소스를 담아두는 코드의 예는 아래와 같습니다.

List<Resource> items = new List<Resource>() { new Resource(0), new Resource(1), new Resource(2), new Resource(3) };
ResourcePool<Resource> objPool = new ResourcePool<Resource>(items);

실제 리소스 풀은 스레드를 통해 활용될 때에 그 의미가 있습니다. 예를 들어 앞서 작성한 코드들을 전제로 아래의 코드처럼 말입니다.

Parallel.For(1, 50, new ParallelOptions { MaxDegreeOfParallelism = 8 },
    (int i) => {
        Resource r = objPool.Get();

        r.increaseUsingCount();
        Console.WriteLine("[Thread-Index: " + i + "] " + r.toString());

        // Some Operation
        Thread.Sleep(new Random().Next(600, 3000));
        // .

        objPool.Release(r);
    });

위의 코드는 총 49개의 스레드를 만들고, MaxDegreeOfParallelism에서 지정한 값이 8만큼, 최대 8개의 스레드만을 동시에 실행하도록 하며, 람다 함수를 통해 실행할 스레드 코드를 지정하고 있습니다.

카테고리C#

답글 남기기

이메일 주소는 공개되지 않습니다. 필수 필드는 *로 표시됩니다