메인 스레드 (Main Thread)
- 자바 프로그램이 실행되면 JVM은 기본적으로 하나의 스레드를 생성하며, 이 스레드가 메인 스레드이다.
- 메인 스레드는 public static void main(String[] args) 메서드를 실행하며, 자바 프로그램의 진입점 역할을 한다.
- 메인 스레드는 자바 프로그램의 생명주기를 관리하며, 프로그램의 기본 스레드로 작동한다.
특징
1. 프로그램의 시작점
- 메인 스레드는 main() 메서드를 호출하며, 모든 프로그램 실행은 여기서부터 시작된다.
2. 프로그램 종료 관리
- 자바 프로그램은 Main Thread와 그에 의해 생성된 모든 스레드가 종료될 때 프로그램이 종료된다.
3. 멀티 스레드 프로그램의 조정
- 메인 스레드는 다른 사용자 정의 스레드를 생성하거나 조정할 수 있다.
- 메인 스레드가 종료되더라도 다른 스레드가 실행 중이면 프로그램은 계속 실행된다.
4. 우선순위
- 메인 스레드의 기본 우선순위는 Thread.NORM_PRIORITY (값:5)로 설정된다.
생성과 속성
이름: 기본적으로 "main"으로 설정된다.
우선순위 : 5 (기본 값)
스레드 그룹: 메인 스레드는 기본적으로 "main" 이라는 스레드 그룹에 속한다.
종료
- main() 메서드 수행이 완료되면 메인 스레드는 종료된다.
- 메인 스레드의 종료가 프로그램의 종료를 의미하지는 않는다.
- 모든 일반 스레드가 종료되어야만 프로그램이 종료됩니다.
싱글 스레드 (Single Thread)
- 메인 스레드에서와 같이 작업 진행이 순차적으로 진행된다.
- 하나의 프로세스에서 하나의 스레드로만 진행한다.
- 단일 레지스터 셋과 단일 스택으로 구성된다.
- Context Switching (컨텍스트 스위칭) 작업이 요구되지 않는다.
- 자원에 대한 공유 문제가 발생하지 않으므로, 동시성 제어가 필요하지 않다.
장점
- 자원 접근에 대한 동기화를 고려하지 않아도 된다.
- 여러 개의 스레드가 프로세스의 자원을 공유하면, 각 스레드가 자원 접근에 대해서 접근 제어를 해야한다.
- 동시 접근, 동일한 작업을 실행하면 자원 공유에 따른 문제가 발생할 수 있다.
- 컨텍스트 스위칭 작업을 요구하지 않는다.
- 컨텍스트 스위칭 : 프로세스 또는 스레드를 교체하는 작업
- 멀티 스레드 환경에서는 컨텍스트 스위칭을 통해 실시간 처럼 보이게함.
- 컨텍스트 스위칭에 따른 오버헤드 비용이 발생하지 않음.
- 단순한 계산 작업이라면 멀티 스레드 보다 싱글 스레드 기반으로 개발하는 것이 효율적이다.
- 스레드간 작업 전환인 컨텍스트 스위칭이 발생하면, 실행 중인 스레드의 레지스터 정보를 저장하고 다른 스레드의 레지스터 정보를 CPU 레지스터로 옮기는 작업을 수행하므로 시간 소모가 발생
- 개발 및 운영 비용을 줄일 수 있다.
단점
- Multi-Core (다중 코어)를 기반으로 발전하고 있는 CPU 자원을 최대로 활용하지 못한다.
- 싱글 스레드는 동시 실행 가능한 여러 개의 코어가 있더라도 하나의 코어만을 사용해 효율적인 자원 활용이 힘듦
- 프로그램 내 모든 작업이 순차적으로 진행되므로, 원하는 시간 내에 작업이 이루어지지 않을 수 있음.
- 정해진 시간 내에 응답을 줘야하는 통신 프로그램의 경우, 특정한 작업으로 인해 응답이 지연되어 끊어질 수 있음.
- 여러개의 작업을 순차적으로 처리할 경우, 복잡한 작업으로 인해 단순한 작업의 완료 시간이 길어질 수 있음.
- 장애 대응에 어려울 수 있음.
- 작업 수행 중 복구 불능 상태가 되었을 때, 프로그램 종료 후 재실행 이외의 방법이 없음.
멀티 스레드 (Multi-Thread)
- 프로그램 내에서 두 개 이상의 작업을 동시에 실행할 수 있다.
- 하나의 프로세스를 다수의 실행 단위로 구분하여 자원을 공유한다.
장점
응답성
- 프로그램 일부가 중단되거나 긴 작업을 수행하더라도 프로그램 수행이 지속적으로 유지되어 사용자에 대한 응답성이 증가
- 복구 불능 장애 발생시 해당 스레드를 종료하고, 새로운 스레드를 생성해서 장애를 극복 가능
경제성
- 프로세스 내 자원들과 메모리를 공유하기 때문에 메모리 자원과 시스템 공간을 효율적으로 활용 가능
- 스레드 간 통신에서도 데이터를 주고받을 수 있으며, 프로세스 간의 컨텍스트 스위칭과 달리 스레드 간의 컨텍스트 스위칭은 캐시 메모리를 비울 필요가 없기 때문에 더 빠르게 동작한다. (힙 메모리를 공유)
- 멀티 프로세서의 활용 가능
단점
- 컨텍스트 스위칭, 동기화 등의 이유로 싱글 코어 멀티 스레딩은 스레드 생성시간이 오히려 오버헤드로 작용해 싱글 스레드 보다 느릴 수 있다.
- 공유 자원을 서로 다른 스레드가 동시에 접근하는 경우, 스레드 내에서는 힙 메모리 영역을 공유하기 때문에 다른 스레드에서 사용 중인 변수나 자료구조에 접근하여 엉뚱한 값을 읽어오거나 수정할 수 있다.
- 그렇기 때문에 동기화 처리를 해야함. 즉, 동기화 비용이 발생
데몬 스레드 (Daemon Thread)
- 데몬 스레드는 Java에서 백그라운드 작업을 수행하는데 사용되는 보조 스레드다.
- 메인 스레드나 다른 사용자 스레드를 지원하는 역할을 함.
- 사용자 스레드가 모두 종료되면 자동으로 종료됨.
특징
1. 백그라운드 작업 수행
- 데몬 스레드는 사용자 스레드의 작업을 지원하거나 보조적인 작업을 처리한다.
- 예: JVM의 가비지 컬렉터, 메모리 관리, 로그 기록, 데이터 동기화 등
2. 사용자 스레드에 의존적
- 데몬 스레드는 사용자 스레드가 실행 중 일때만 실행된다.
- 사용자 스레드가 모두 종료되면 JVM은 데몬 스레드를 강제로 종료하고 프로그램 실행을 종료한다.
3. 생명주기 관리
- 데몬 스레드는 독립적으로 실행되지만, JVM의 생명주기에 따라 동작이 종료된다.
- 사용자 스레드가 종료되면 데몬 스레드는 더 이상 실행되지 않는다.
4. 우선 순위
- 일반적으로 낮은 우선순위를 가지며, 사용자 스레드가 실행되지 않을 때 CPU를 사용한다.
- 데몬 스레드의 우선순위는 기본 스레드 우선순위와 동일하게 설정할 수 있다.
생성 및 설정
Java에서 데몬 스레드는 Thread 클래스의 setDaemon(true) 메서드를 사용하여 설정할 수 있다.
public class DaemonThreadExample {
public static void main(String[] args) {
Thread daemonThread = new Thread(() -> {
while (true) {
System.out.println("데몬 스레드 실행 중...");
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
});
// 데몬 스레드로 설정
daemonThread.setDaemon(true);
daemonThread.start();
System.out.println("메인 스레드 종료");
}
}
주요 메서드
- setDaemon(boolean on)
- 스레드를 데몬 스레드로 설정합니다.
- 반드시 스레드가 시작되기 전에 호출해야 하며, 이미 실행 중인 스레드에 대해 호출하면 `IllegalThreadStateException`이 발생합니다.
- isDaemon()
- 해당 스레드가 데몬 스레드인지 확인합니다.
- 반환값: true(데몬 스레드), false(사용자 스레드).
사용 예
public class DaemonThreadCheck {
public static void main(String[] args) {
Thread thread = new Thread(() -> System.out.println("스레드 실행"));
System.out.println("데몬 스레드 여부 (기본값): " + thread.isDaemon());
// 데몬 스레드로 설정
thread.setDaemon(true);
System.out.println("데몬 스레드 여부 (설정 후): " + thread.isDaemon());
thread.start();
}
}
데몬 스레드의 용도
데몬 스레드는 보조적인 역할을 수행하며, 사용자 스레드의 작업을 지원하는 데 자주 사용된다.
- JVM의 가비지 컬렉터
- 백그라운드 데이터 동기화
- 로그 처리
- 타이머 작업
데몬 스레드와 사용자 스레드의 차이
Thread Life Cycle
New
- 스레드가 실행 준비를 완료한 상태로, start() 메서드를 호출하기 전 상태
Runnable
- start()가 호출되어 실행될 수 있는 상태
- 스레드 스케줄링에 따라 CPU에서 실행될 기회를 기다리는 상태
Wait
- 다른 스레드가 통지할 때까지 기다리는 상태
Timed_Wait
- 정해진 시간동안 다른 스레드가 통지할 때까지 기다리는 상태
Blocked
- 사용하고자 하는 객체의 잠금이 풀릴 때까지 대기하는 상태
Terminated
- 실행이 종료된 상
'🚣활동 > NHN Academy' 카테고리의 다른 글
Deadlock (교착 상태) (0) | 2025.02.04 |
---|---|
Thread & Concurrency (1) | 2025.02.04 |
Thread (스레드) (0) | 2025.02.03 |
Process (프로세스) (0) | 2025.02.03 |
Stream (1) | 2025.01.24 |