쓰레드를 미리 만들어서 쓰레드 풀에 저장해두고 일이 들어올 때마다 쓰레드를 할당해 일을 처리. 일을 마치면 반환된 쓰레드를 다시 쓰레드 풀에 넣어둬서 시스템의 전체적인 성능을 높여주는 매커니즘
프레임워크: 프로그램을 구현할 때 제공되는 틀. 프로그램이 완성되면 프레임워크의 부가적인 기능들과 함께 프로그램이 돌아간다.
쓰레드 풀을 대표적인 프레임 워크. 프로그래머가 직접 개발하지 않아도 사용할 수 있다.
쓰레드를 커널 오브젝트로 본다고 가정. 커널 오브젝트는 생성과 소멸에 많은 리소스를 동반한다. (메모리의 할당과 반환, OS에 해당 리소스에 대한 정보를 등록, 커널 모드 - 유저 모드 전환)
쓰레드같은 경우 스케줄러의 관리 대상이기 때문에 OS가 정보를 가지고 있고 + 스케줄러에 의해 감지되어야한다.
처리해야 일이 10개가 있고 쓰레드 하나 당 1개의 일을 맡아서 처리한다고 가정하면, 총 10개의 쓰레드를 생성-소멸해야 한다. 그러나 10개의 일이 동시에 처리되는게 아니라, 시간 텀을 두고 들어온다면? 하나의 쓰레드만 생성하고 해당 쓰레드가 10개의 일을 모두 처리하도록 할 수 있다.
혹은 일이 2개, 3개, 5개.. 매번 다르게 들어온다면? 이 경우 요구되어지는 최대 쓰레드의 개수만큼 쓰레드를 미리 만들어두고, 이를 풀에 저장. 2개의 일이 들어왔을 때 쉬고 있는 2개의 쓰레드를 풀에서 꺼내 일을 처리. 먼저 나간 쓰레드의 일이 아직 안 끝났을 경우 풀에서 대기 중인 3개의 쓰레드가 다음번에 들어온 일을 처리. 그리고 일을 마친 쓰레드는 소멸되는게 아니라 다시 풀에 저장.
이처럼 쓰레드 풀을 통해 쓰레드의 생성-소멸을 줄일 수 있고, 이는 성능(속도) 향상으로 이어진다.

// 작업이라는 건, 함수로 구현 가능함. 즉, 작업의 기본 단위는 함수.
// 반환 자료형과 매개변수 목록은 프로그래머 마음대로 가능.
typedef void(*WORK)(void);
// 사실 쓰레드 풀은 Framework라 했음. 즉, OS에서 제공되는 API들.
// 구현 하려면 마치 윈도우즈가 쓰레드를 관리하듯이, 우리도 비슷하게 구현 해보자.
// 이를 위해서 아래와 같은 구조체가 필요함. 단순하게 두 멤버만 추가함.
typedef struct __WorkerThread
{
HANDLE hThread;
DWORD idThread;
// 이외에도 우선순위와 같은 멤버도 추가 가능. 일의 성격, etc ...
} WorkerThread;
// Work와 Thread 관리를 위한 구조체. Thread Pool의 기본적인 모델. 꼭 이렇게 구현하라는 표준이 아님에 유의.
typedef struct __ThreadPool
{
// Work을 등록하기 위한 배열. 이는 풀 밖에 있을 수도 있음.
WORK workList[WORK_MAX];
// Thread 정보와 각 Thread별 Event Object
WorkerThread workThreadList[THREAD_MAX]; // Thread 정보를 저장할 수 있는 배열
HANDLE workerEventList[THREAD_MAX]; // Event Object 정보를 저장할 수 있는 배열
// Work에 대한 정보
DWORD idxOfCurrentWork; // 대기 1순위 Work Index.
DWORD idxOfLastAddedWork; // 마지막 추가 Work Index + 1.
// Number of Thread
DWORD idxOfThread; // Pool에 존재하는 Thread의 갯수.
} gThreadPool;

다시 말해, 쓰레드는 자신에게 할당된 이벤트 오브젝트가 Signaled 상태인지 확인하기 위해 WaitForSingleObeject() 함수를 호출하고, 반환되면 GetWorkFromPool()를 통해 작업(함수 포인터)을 얻고 다시 WaitForSingleObeject() 호출.
이처럼 쓰레드 풀은 일이 끝나면 자기 스스로 반복되는 구조.

Intelligent Pool쓰레드의 개수를 상황에 따라 몇 개를 생성하고 소멸할지 중간에 결정 가능한 풀.
일이 생겼을 때 쓰레드를 생성하고 풀에 저장하려면 시간이 걸리기 때문에, 일이 없더라도 쓰레드 풀에는 미리 쓰레드가 저장되어 있어야 한다.
작업이 없을 때 쓰레드 풀에 쓰레드를 몇 개 까지 만들어서 저장해둘 것인지, 그리고 작업량이 생각보다 많을 때 쓰레드를 몇개 더 생성할지, 반대로 작업이 생각보다 없을 때 쓰레드를 몇 개 소멸할지에 대한 결정이 가능하다.