스레드(Thread)
스레드(Thread)
- 프로세스 내에서 할당된 자원을 이용해 실제 작업을 수행하는 작업 단위
- 모든 프로세스는 하나 이상의 스레드를 가지며 각각 독립적인 작업 단위를 가짐
- 프로세스 : 스레드 = 공장 : 일꾼
하나의 새로운 프로세스를 생성하는 것보다 하나의 새로운 스레드를 생성하는 것이 더 적은 비용이 든다.
스레드 강의 찾아보다가 어디선가 들은 말.
프로세스
- 실행 중인 프로그램
- 자원(resources)과 스레드로 구성
- 자원: 메모리, CPU 등
- 프로그램이 실행 될 때마다 개별적으로 생성
- 프로그램을 수행할 때 필요한 데이터와 메모리 등의 할당 받은 자원, 하나 이상의 스레드로 구성
메인 스레드
- main 메서드의 코드를 수행하는 스레드
- 모든 자바 프로그램은 메인 스레드가 main() 메소드를 실행하며 시작
- 사용자 스레드
- main() 메소드의 코드가 순차적으로 실행되고, return을 만나면 종료
- 필요에 의해 작업 스레드들을 만들어서 병렬 코드를 실행 가능(멀티 스레드를 이용한 멀티 태스킹)
- 실행 흐름이라고 생각
프로세스 종료
- 싱글 스레드: 메인 스레드(사용자 스레드)가 종료되면 프로세스도 종료
- 멀티 스레드: 실행중인 스레드가 하나라도 있다면 프로세스가 종료되지 않음
멀티 프로세스 / 멀티 스레드
- 멀티 프로세스 : 각각의 프로세스를 독립적으로 실행(ex.크롬 창 2개 띄워놓고 실행하는 것)
- 멀티 스레드 : 하나의 프로세스 내에서 여러 스레드가 동시에 작업을 수행
싱글 스레드 / 멀티 스레드
- 싱글 스레드 : 메인 스레드 하나만 가지고 작업을 처리 > 한 작업씩 차례대로 처리해 나감.
- 멀티 스레드 : 메인 스레드 외의 추가적인 스레드를 이용하여 병렬적으로 작업을 처리
- 실행 순서는 OS 스케쥴러가 결정
멀티 스레드 장점
- 자원을 보다 효율적으로 사용 가능
- 사용자의 대한 응답성 향상
- 애플리케이션의 응답성 향상
- 작업이 분리되어 코드가 간결
- CPU 사용률 향상
멀티 스레드 단점
- 동기화(Synchronization)에 주의
- 교착 상태(dead-lock)가 발생하지 않도록 주의
- 프로그래밍 시 고려해야 할 사항이 다수
- 각 스레드가 효율적으로 고르게 실행될 수 있도록 확인
멀티 스레드 Context Switching
- Context Switching 발생으로 싱글 스레드보다 시간이 조금 더 걸림
- 현재 진행하고 있는 Task(Process, Thread)의 상태를 저장하고 다음 진행할 Task의 상태 값을 읽어 적용하는 과정
스레드의 I/O 블락킹(Blocking)
- 입출력 시 작업 중단
- 싱글 스레드에서 사용자의 입력 시간을 기다리는 구간
스레드 구현과 실행
- 스레드 생성 후에
- start() 호출
- Thread 클래스 상속
- java는 단일 상속만을 지원하기 때문에 다른 클래스를 상속 받기 까다로워짐
class ThreadTest extends Thread { // Thread 클래스 상속
public void run() { // Thread 클래스의 run() 메서드 오버라이딩(재정의) 필요
// 스레드가 수행 할 작업 작성
}
}
ThreadTest t = new ThreadTest(); // 스레드 생성
t.start(); // 스레드 실행
- Runnable 인터페이스 구현
- run() 추상 메서드 하나만 갖고 있는 인터페이스
class ThreadTest implements Runnable { // 인터페이스
public void run() { // Runnable 인터페이스의 run() 구현
// 스레드가 수행 할 작업 작성
}
}
Runnable r = new ThreadTest();
Thread t = new Thread(r);
// Thread t = new Thread(new ThreadTest());
t.strat();
start() / run()
- start() 호출 시 새로운 스택에 run()이 담기고 기존에 있던 start()는 종료
메서드
- t.join() : t 스레드가 끝날 때까지 대기
- currentg : 현재 스레드 이름 반환
스레드 스케줄링
- 스레드가 코어의 수보다 많을 경우 스레드를 어떤 순서로 동시성을 실행할 것인지 결정
- 스케줄링에 의해 번갈아가면서 run() 메서드 실행 / 동시성(번갈아가면서)
스레드의 우선 순위(Priority)
- 작업 중요도에 따라 스레드의 우선 순위를 다르게 하여 특정 스레드가 더 많은 작업 시간을 갖게 하도록 OS 스케쥴러에 전달
- 1부터 10까지의 우선 순위 번호 부여(번호가 높을 수록 우선 순위가 높음) - JVM / window에서는 32단계
- 기본 값은 5
순환 할당 방식(Round-Robin)
- 시간 할당량(Time Slice)를 정하여 하나의 스레드를 정해진 시간만큼 실행시키는 방식
- JVM에 의해 결정(코드로 제어 불가)
스레드 제어
- 효율적이고 정교한 스케줄링을 위한 스레드 상태를 제어
메서드 | 설명 |
---|---|
static void sleep() | 지정된 시간 동안 스레드 일시 정지. 지정한 시간이 지나면 다시 실행 상태로 변경 |
void interrup() | sleep() / join() 에 의해 일시 정지 상태의 스레드를 실행 대기 상태로 변경. InterruptException이 발생하여 일시 정지 상태를 벗어남 |
void join() | 지정된 시간 동안 스레드 실행. 지정된 시간이 지나거나 작업 종료 시 join()을 호출한 스레드로 다시 돌아와 실행 진행 |
void wait() | 동기화된 블럭 안에서 다른 스레드가 이 객체의 notify() / notifyAll()을 호출하거나 지정된 시간이 지날 때까지 현재의 스레드를 대기 시킴 |
void notify() | 동기화된 블록 안에서 호출한 객체 내부에 대기 중인 스레드를 깨움. 여러 스레드가 있을 경우 임의의 스레드 하나에만 통보 |
void yield() | 실행 중 다른 스레드에게 실행을 양보하고 자신은 실행 대기 상태로 변경 |
스레드 동기화
- 한번에 한 개의 스레드만 프로세스 공유 자원(객체)에 접근할 수 있도록 락(Lock)을 걸어 다른 스레드가 진행 중인 작업에 간섭하지 못하도록 하는 것.
- Synchronized 키워드 사용
// 동기화 메서드
public synchronized void method() {
// 한 개의 스레드만 실행할 수 있음
}
// 동기화 블럭
public void method1() {
synchronized (공유객체) {
// 한 개의 스레드만 실행할 수 있음
}
}
데몬 스레드
- 일반 스레드를 돕는 보조 스레드
- 일반 스레드 종료 시 종료
- setDaemon(true)를 호출하여 생성
- start() 호출 전(IllegalThreadStateException 발생)