프로세스(프로그램)이 메모장, 크롬, MMORPG 게임이 실행되고 있다고 가정하자.
각 프로그램에는 쓰레드가 존재하고 메모장에 1개, 크롬에 1개, MMORPG에 2개가 있다.
CPU의 코어는 한번에 하나의 쓰레드만 동작시킬 수 있는데,
만약 1개의 코어라면? 각 쓰레드를 굉장히 빠른 속도로 이동하며 프로그램을 동시에 돌아갈 수 있도록 만든다.
코어가 2개라면? 2개의 코어가 굉장히 빠른 속도로 이동하며 프로그램을 동시에 돌아갈 수 있도록 만든다.
가장 좋은 방법은 코어와 쓰레드의 개수를 일치시키는 것이다.
코어가 굉장히 빠른 속도로 쓰레드를 돌아가며 프로그램을 실행시키는 것보단
하나의 코어가 하나의 쓰레드에 집중하며 프로그램을 실행시키는 것이 효율 차원에선 이득이다.
간단하게 쓰레드에 대해서 알아보았으니.. C#으로 쓰레드를 생성해보자.
1. ServerCore.cs 생성
namespace ServerCore
{
class Program
{
static void Main(string[] args)
{
}
}
}
2. 쓰레드 생성
namespace ServerCore
{
class Program
{
static void MainThread()
{
Console.WriteLine("Hello Thread");
}
static void Main(string[] args)
{
Thread t = new Thread(MainThread);
t.Start();
Console.WriteLine("Hello World");
}
}
}
실행해보면(ctrl + f5)
쓰레드가 생성되어 실행된 것을 확인할 수 있다.
3. 쓰레드 무한반복
namespace ServerCore
{
class Program
{
static void MainThread()
{
while (true)
{
Console.WriteLine("Hello Thread");
}
}
static void Main(string[] args)
{
Thread t = new Thread(MainThread);
t.Start();
Console.WriteLine("Hello World");
}
}
}
메인 메서드가 끝날때까지 쓰레드가 계속 실행되는 모습
4. 쓰레드 Join
namespace ServerCore
{
class Program
{
static void MainThread()
{
while (true)
{
Console.WriteLine("Hello Thread");
}
}
static void Main(string[] args)
{
Thread t = new Thread(MainThread);
t.Start();
t.Join();
Console.WriteLine("Hello World");
}
}
}
Join은 실행된 쓰레드가 종료될 때까지 대기하는 메서드다.
실행시켜보면
무한 쓰레드 굴레에 빠져서 메모리를 잡아먹는 것을 알 수 있다.
5. 쓰레드 isBackground
namespace ServerCore
{
class Program
{
static void MainThread()
{
while (true)
{
Console.WriteLine("Hello Thread");
}
}
static void Main(string[] args)
{
Thread t = new Thread(MainThread);
t.IsBackground = true;
t.Start();
//t.Join();
Console.WriteLine("Hello World");
}
}
}
isBackground는 background 실행 여부를 묻는다.
background에서 실행이 된다면 아무리 쓰레드가 무한루프를 돌아도 Main쓰레드가 종료되면 종료된다.
자자잔.. Thread가 실행되다가 Main이 끝나니 정지했다.
6. 쓰레드 풀, 풀링
오브젝트 풀을 들어본 적이 있나요? 오브젝트 풀은 오브젝트를 새롭게 생성하는 것이 아니라 생성해둔 오브젝트를 풀에 넣어두고 필요할 때 쓰던 방식이다. 덕분에 메모리를 효과적으로 관리할 수 있다.
쓰레드 풀도 마찬가지다. 쓰레드를 몇 개 생성해서 풀에 넣어둔 다음에 사용하는 것이다. 이런 방식을 쓰레드 풀링이라고 한다.
namespace ServerCore
{
class Program
{
static void MainThread(object state)
{
while (true)
{
Console.WriteLine("Hello Thread");
}
}
static void Main(string[] args)
{
int a = 1;
int b = 5;
ThreadPool.GetMinThreads(out a, out a);
ThreadPool.GetMaxThreads(out b, out b);
for(int i = 0; i < b; i++)
{
ThreadPool.QueueUserWorkItem((obj) => { while (true) { } });
}
ThreadPool.QueueUserWorkItem(MainThread);
//Thread t = new Thread(MainThread);
//t.IsBackground = true;
//t.Start();
//t.Join();
//Console.WriteLine("Hello World");
}
}
}
쓰레드 풀을 최소 1, 최대 5만큼 생성하고 QueueUserWorkItem()으로 쓰레드를 실행한다.
결과는?
총 5개의 쓰레드를 생성했고 5개의 쓰레드를 모두 소진하였으니 for문 밖에 쓰레드를 실행하라는 메서드는 작동되지 않는다.
7. 테스크
만약 시간이 오래 걸리는 작업이 쓰레드를 붙잡아두면 어떻게 될까? 풀에 있던 쓰레드가 소진되어 시스템이 먹통이 될 수 있다. 그래서 등장한 것이 테스크다.
테스크는 일종의 작업 단위다. 비동기 프로그래밍을 위해 사용되는 개념 중 하난데, 프로그램이 특정 작업을 기다리는 동안 멈추지 않고 다른 작업을 처리할 수 있게 해주는 방식이다.
테스크는 어떤 작업이 완료될 때까지 기다릴 필요 없이 실행을 시작할 수 있는 방법을 제공한다. 백그라운드 스레드에서 사용할 수 있고 주 스레드는 테스크가 완료될 때까지 기다리지 않고 다른 작업을 이어나갈 수 있다.
'동식이 취업시키기 작전 > Unity' 카테고리의 다른 글
[Unity] Slider 커스텀 | Silder Fill Area 딱 맞게 조절하기(채우기) | Handle 조절 | Handle 직접 조작 못하게 (1) | 2024.06.28 |
---|---|
Unity에서 엑셀파일, csv파일 데이터 읽기(겁나 상세하게 적음) (1) | 2024.06.07 |
[Unity] 에셋 프리팹이 어둡게 나올 때(feat. Built-in, URP) (1) | 2023.12.21 |
[융합 프로젝트] AddListener로 필수정보 입력 후 버튼 활성화(feat. Text mesh pro) (0) | 2023.11.05 |
[융합 프로젝트] 캐릭터 선택 씬 만들기 (0) | 2023.11.05 |