* Thread State (Thread 상태)
모든 Thread 는 상태를 가지고 있으며, ThreadState 읽기 전용 속성을 통해 상태를 파악할 수 있다.
Thread 는 생성되어 종결될 때 까지 최소한 하나의 상태에 놓이게 된다.
하나의 Thread 가 생성에서 종료 될 때까지의 상태를 간단하게 기술하면
a. 최초 Thread 생성 ? Unstarted
b. Thread 실행(Start 호출) ? Running
c. 실행 종료 ? Stoped
* Thread 상태 흐름도

- Unstarted : new Thread() 로 최초 Thread 를 생성한 시점이 바로 Unstarted 상태가 된다.
- Runnable : 생성된 Thread 의 Start 를 호출하면 Runnable(실행가능한) 상태가 된다.
이때 실제 현시점에 실행중인(Running) Thread와 후보Thread 로 나뉜다.
후보 Thread 란 현 시점에 cpu가 실행하고 있지는 않지만 실행Queue 에
놓여 있어 cpu 점유를 할 예정인 Thread 이다.
- Suspended : 실행중인 Thread 의 Suspend 를 호출하면 Runnable 상태에서 Suspended
상태로 전환한다. 즉 Thread 는 일시 중단 된다.
일시 중단된 Thread 는 Resume 호출로 다시 Runnable 상태로 전환된다.
- WaitSleepJoin : 실행중인 Thread 가 Wait,Sleep,Join 등에 의해 Thread 가 차단된다.
- Stoped : Thread 의 실행을 다 했거나 Abort 호출에 응답한 경우 중지 상태가 된다.
닷넷에서는 Thread 의 상태를 위한 ThreadState 열거형을 제공한다. 다음은 ThreadState 에 대한 MSDN 설명이다.
멤버 이름 |
설명 |
값 |
Aborted |
스레드가 Stopped 상태에 있습니다. |
256 |
AbortRequested |
스레드에 Thread.Abort 메서드가 호출되었지만 해당 스레드는
자신을 종결시키려는 보류된 System.Threading.ThreadAbortException을 받지 못했습니다. |
128 |
Background |
해당 스레드는 전경 스레드와 반대인 배경 스레드로 실행됩니다.
이 상태는 Thread.IsBackground 속성을 설정하여 제어합니다. |
4 |
Running |
해당 스레드가 차단되지 않고 시작되었고 보류된 ThreadAbortException 이 없습니다. |
0 |
Stopped |
스레드가 중지되었습니다. |
16 |
StopRequested |
스레드를 중지하도록 요청했습니다. 이는 내부 전용입니다. |
1 |
Suspended |
스레드가 일시 중단되었습니다. |
64 |
SuspendRequested |
스레드를 일시 중단하도록 요청하고 있습니다. |
2 |
Unstarted |
스레드에 Thread.Start 메서드가 호출되지 않았습니다. |
8 |
WaitSleepJoin |
Wait, Sleep 또는 Join을 호출한 결과 스레드가 차단되었습니다. |
32 |
또한 Thread 의 동작에 따른 상태 변화를 나타낸다.
동작 |
ThreadState |
공용 언어 런타임 내에서 스레드를 만듭니다. |
Unstarted |
스레드에서 Start를 호출합니다. |
Running |
스레드가 실행을 시작합니다. |
Running |
스레드에서 Sleep을 호출합니다. |
WaitSleepJoin |
스레드에서 다른 개체에 있는 Wait를 호출합니다. |
WaitSleepJoin |
스레드에서 다른 스레드에 있는 Join을 호출합니다. |
WaitSleepJoin |
다른 스레드에서 Interrupt를 호출합니다. |
Running |
다른 스레드에서 Suspend를 호출합니다. |
SuspendRequested |
스레드가 Suspend 요청에 응답합니다. |
Suspended |
다른 스레드에서 Resume을 호출합니다. |
Running |
다른 스레드에서 Abort를 호출합니다. |
AbortRequested |
스레드가 Abort 요청에 응답합니다. |
Stopped |
스레드가 종결됩니다. |
Stopped |
* Demo
그럼 이제 간단한 데모로 Thread 의 상태 변화를 알아보자.
주(Main) Thread 에서 Worker Thread 를 하나 Worker Thread 를 생성하여 Worker Thread 의 상태를 진행별로 알아보는 데모이다. 중간에 Worker Thread 의 우선 실행을 위해 주 Thread 의 실행을 잠시 멈춘다(Sleep)
이렇게 하지 않으면 주 Thread 가 먼저 실행종료 될 수가 있어 Worker Thread 의 중지 상태를 알 수 없게 되기 때문에 잠시 주 Thread 를 Sleep 시킨다
public class Class
{
public static void Main()
{
//메인(주) 쓰레드 이름 부여
Thread.CurrentThread.Name = "Main Thread";
//Worker Thread 생성
ThreadTest tt = new ThreadTest();
ThreadStart ts = new ThreadStart(tt.ThreadMethod);
Thread thread= new Thread(ts);
//Worker Thread 에 이름 부여
thread.Name = "Worker Thread";
//Worker Thread 를 생성만 하고 시작하지 않은 상태에서 상태를 찍어 보자
Console.WriteLine(thread.ThreadState.ToString());
//Worker Thread 시작
thread.Start();
//메인 쓰레드를 잠시 중단 시킨다(Worker 쓰레드를 먼저 실행시키기 위해..)
Thread.Sleep(100);
//Worker 쓰레드의 종료를 찍어 본다
Console.WriteLine(thread.ThreadState.ToString());
Console.WriteLine(Thread.CurrentThread.Name+ "종료" );
}
}
public class ThreadTest
{
private int count = 0;
public void ThreadMethod()
{
while(count < 10)
{
Console.WriteLine(Thread.CurrentThread.Name +":" + count++);
if(count == 5)
{
//이 Thread 실행 중간에 상태를 찍어 보자
Console.WriteLine(Thread.CurrentThread.ThreadState.ToString()); }
}
Console.WriteLine(Thread.CurrentThread.Name+ "종료" );
}
} |
- 결과

데모 결과에서 나타나듯이 Worker Thread 가 처음 생성된 시점에 Unstarted 이다.
그리고 실행 중간에는 Running 상태 이고 실행이 종료되면 Stopped 가 된다.
이제 코드를 살짝 바꾸어 Suspend/Resume 의 상태 변화를 살펴 보자.
public class Class
{
public static void Main()
{
Thread.CurrentThread.Name = "Main Thread";
ThreadTest tt = new ThreadTest();
ThreadStart ts = new ThreadStart(tt.ThreadMethod);
Thread thread= new Thread(ts);
thread.Name = "Worker Thread";
Console.WriteLine(thread.ThreadState.ToString());
thread.Start();
Thread.Sleep(100);
//Worker 쓰레드의 현재 상태를 알아본다 (일시 중지 상태)
Console.WriteLine(thread.ThreadState.ToString());
thread.Resume();
Console.WriteLine(Thread.CurrentThread.Name+ "종료" );
}
}
public class ThreadTest
{
private int count = 0;
public void ThreadMethod()
{
while(count < 10)
{
Console.WriteLine(Thread.CurrentThread.Name +":" + count++);
if(count == 5)
{
//이 Thread 실행 중간에 일시 중지 시킨다
Thread.CurrentThread.Suspend();
//이 Thread 가 Resume 되면 아래가 실행될 것이다 Console.WriteLine(Thread.CurrentThread.ThreadState.ToString());
}
}
Console.WriteLine(Thread.CurrentThread.Name+ "종료" );
}
} |
- 결과

Worker Thread 는 Suspend 호출로 일시 중단 되었다가 Resume 호출로 다시 Running 상태가 됨을
알 수 있다
이번에는 Join 을 사용해 Thread 들의 상태 변화를 살펴 보자
public class Class
{
public static void Main()
{
Thread.CurrentThread.Name = "Main Thread";
ThreadTest tt = new ThreadTest();
ThreadStart ts = new ThreadStart(tt.ThreadMethod);
Thread thread= new Thread(ts);
thread.Name = "Worker Thread1";
ThreadTest2 tt2 = new ThreadTest2();
ThreadStart ts2 = new ThreadStart(tt2.ThreadMethod);
Thread thread2 = new Thread(ts2);
thread2.Name = "Worker Thread2";
tt.myThread = thread;
tt2.myThread = thread2;
tt.anotherThread = thread2;
tt2.anotherThread = thread;
thread.Start();
thread2.Start();
Console.WriteLine(Thread.CurrentThread.Name+ "종료" );
}
}
public class ThreadTest
{
public Thread myThread;
public Thread anotherThread;
private int count = 0;
public void ThreadMethod()
{
while(count < 10)
{
Console.WriteLine(Thread.CurrentThread.Name +":" + count++);
if(count == 5)
{
//count 4 까지 실행하다가 Worker Thread2가 실행완료 될때 까지
//이 Thread 는 차단된다.
//Worker Thread2가 실행이 완료되면 다시 Worker Thread1이 계속 실행될 것이다.
this.anotherThread.Join();
}
}
Console.WriteLine(Thread.CurrentThread.Name+ "종료" );
}
}
public class ThreadTest2
{
public Thread myThread;
public Thread anotherThread;
private int count = 0;
public void ThreadMethod()
{
//Worker Thread1 의 우선실행을 위해 이 Thread 를 잠시 멈춘다
//Worker Thread1의 count 가 5되는 시점에 Join이 호출되어
//이 Thred의 실행완료가 보장될 것이다
Thread.Sleep(300);
while(count < 10)
{
//이 Thread 의 Sleep 이 있어도 이 Thread 의 실행이 완료될 때까지
//다른 Thread 는 차단될 것이다
Thread.Sleep(50);
Console.WriteLine("Worker Thread1 상태 : " + this.anotherThread.ThreadState.ToString());
Console.WriteLine(Thread.CurrentThread.Name +":" + count++);
}
Console.WriteLine(Thread.CurrentThread.Name+ "종료" );
}
} |
- 결과

결과에서 나타나듯이 Worker Thread 1이 4까지 실행되다가 Worker Thread 2 가 실행이 완료 되는
시점에 다시 Worker Thread1 이 실행된다.
이처럼 Join 을 호출한 Thread(Worker Thread2) 가 종료될 때까지 Worker Thread1은
차단되게 된다.
이때 Worker Thread1은 WaitSleepJoin 상태가 된다.