[JAVA]쓰레드

ggamang·2022년 9월 21일
0

JAVA&Spring

목록 보기
4/27

쓰레드

프로세스

실행 중인 프로그램. 자원과 쓰레드로 구성

쓰레드

프로세스 내에서 실제 작업을 수행. 모든 프로세스는 최소 하나의 쓰레드를 갖고 있다. 프로세스보다 쓰레드 생성 비용이 더 적다

멀티쓰레드의 장점

시스템 자원을 보다 효율적으로 사용할 수 있다
사용자에 대한 응답성이 향상된다
작업이 분리되어 코드가 간결해진다

멀티쓰레드의 단점

동기화에 주의해야한다
교착상태가 발생하지 않도록 유의해야 한다
각 쓰레드가 효율적으로 고르게 실행될 수 있게 해야 한다.

쓰레드의 구현과 실행

쓰레드 구현

  1. Thread 클래스 상속
MyThread t1 = new MyThread();
t1.start();
  1. Runnable 인터페이스 구현(권장)
Runnable r = new MyThread2();
Thread t2 = new Thread(r);	// Thread(Runnable r)
t2.start();

쓰레드의 실행

쓰레드 생성 후 start() 호출하여 쓰레드 실행
실행순서는 OS의 스케줄러가 결정한다

main 쓰레드

main메서드의 코드를 수행하는 쓰레드

쓰레드는 '사용자 쓰레드'와 '데몬 쓰레드' 두 종류가 있다
실행 중인 사용자 쓰레드가 하나도 없을 때 프로그램은 종료된다

I/O blocking

입출력 시 작업이 중단되는 현상
☞ 외부의 입출력 대기 시간 동안 다른 쓰레드 작업이 가능하기에 멀티쓰레드가 더 효율적이다

쓰레드의 우선순위

우선순위를 조정하여 특정 쓰레드가 더 많은 작업시간을 갖게 할 수 있다

void setPriority(int newPriority)
int getPriority()

쓰레드 그룹

서로 관련된 쓰레드를 그룹으로 묶어서 다룰 수 있다
모든 쓰레드는 반드시 하나의 쓰레드 그룹에 포함되어 있어야 한다
쓰레드 그룹을 지정하지 않고 생성했다면, main 쓰레드 그룹에 속한다

ThreadGroup(String name)
ThreadGroup(ThreadGroup parent, String name)

데몬 쓰레드

일반 쓰레드의 작업을 돕는 보조적인 역할 수행
일반 쓰레드 모두 종료 시 자동적으로 종료
가비지 컬렉터, 자동저장, 화면 자동갱신 등에 사용
무한루프와 조건물을 통해 구현 - 실행 후 대기, 특정조건 만족 시 작업 수행 후 다시 대기하는 형태

boolean isDaemon()
void setDaemon(boolean on)	// 반드시 start() 호출 전에 실행되어야 함

쓰레드의 상태

  1. NEW : 생성되고 아직 start() 미호출
  2. RUNNABLE : 실행 중, 실행 가능한 상태
  3. BLOCKED : 일시정지 된 상태(lock 해지 대기)
  4. WAITING, TIMED_WAITING : 쓰레드 작업이 종료되진 않았지만 실행가능하지 않은 상태
  5. TERMINATED : 작업 종료

쓰레드의 실행제어

쓰레드의 실행을 제어할 수 있는 메서드

static void sleep(long millis)	// 일시정지 시키기
void join()	// 다른 쓰레드 실행을 기다리기
void interrupt()	// 일시정지인 쓰레드를 깨워서 실행대기로 만드는 것
void stop()	// 즉시 종료
void suspend()	// 일시 종료
void resume()	// 실행 대기 상태
static void yield()	// 실행 시간을 다른 쓰레드에 양보

sleep()

현재 쓰레드를 지정된 시간동안 멈추게 한다
static : 쓰레드 자기 자신한테만 동작 적용 가능
(다른 특정 쓰레드를 지정해서 멈추게 하는 것은 불가)
예외처리를 필수로 해야 한다

interrupt()

대기상태(WAITING)인 쓰레드를 실행대기(RUNNABLE)로 만든다

suspend()

쓰레드 일시정지

resume()

쓰레드 재개

stop()

쓰레드 완전 정지

☞ suspend(), resume(), stop()은 교착상태에 빠지기 쉬워 deprecated 되었다.

join()

지정된 시간동안 특정 쓰레드가 작업하는 것을 기다린다
(시간 지정 없으면 작업이 모두 끝날 때까지 기다린다)
예외처리를 필수로 해야한다

yield()

남은 시간을 다음 쓰레드에게 양보하고, 자신은 실행 대기한다

쓰레드의 동기화

한 쓰레드가 진행 중인 작업을 다른 쓰레드가 간섭하지 못하게 막는 것

임계 영역

간섭받지 않아야 하는 문장 ☞ lock을 얻은 단 하나의 쓰레드만 출입 가능

임계 영역 설정방법

  1. 메서드 전체
public synchronized void calcSum() {

}
  1. 특정 영역
synchronized(참조변수) {

}

wait(), notify()

동기화의 효율을 높이기 위해 사용
Object 클래스에 정의, 동기화 블록 내에서만 사용 가능

  • wait() : 객체의 lock을 풀고 쓰레드를 waiting pool에 넣는다
  • notify() : waiting pool에서 대기 중인 쓰레드 중 하나를 꺠운다
  • notifyAll() : waiting pool에서 대기중인 모든 쓰레드를 깨운다

☞ 단점 : waitingPool에 있는 쓰레드를 특정해서 깨울 수 없어서 대안으로 lock & condition이 있다

0개의 댓글