728x90
개요
- 여러 가지 일을 병행하는 멀티태스킹은 프로세스 기반, 스레드 기반으로 구현할 수 있습니다.
프로세스 기반
- 여러 프로그램이 병행으로 실행되는 것
- 프로세스가 생성될 때마다 새로운 메모리 영역을 할당받음
- 프로세스 실행에 필요한 새로운 시스템 자원을 할당받음
스레드 기반
- 프로그램 내부에서 여러 작업이 병행으로 실행되는 것
- 프로그램의 프로세스에서 사용하는 자원과 메모리를 공유
- 스레드를 실행하기 위한 자원만 필요
- 스레드 == 경량 프로세스
- 멀티 스레드 환경에서는 모든 스레드가 종료되어야 프로그램이 종료됨
스레드의 목적
- 멀티 스레드를 구현해야 하는 상황
여러 사용자의 동시 요청 처리
외부 데이터 IO 작업
스레드 활용
- 스레드 생성
java.lang.Thread
클래스를 상속Runnable
인터페이스를 구현해서 Thread를 생성할 때 매개변수로 주입- Thread 클래스도 Runnable 인터페이스를 구현한 클래스입니다.
- Thread에서 수행할 작업은
run()
에 구현해야 합니다. - Thread의
start()
를 이용하여run()
을 호출하여 작업을 수행합니다. start()
를 실행하면 스레드는실행 대기 상태
가 되어 JVM의 스케줄링에 따라 작업을 수행합니다.- 스레드는 JVM의 스케줄링에 의해서 실행되기 때문에 여러 스레드의 작업 순서는 매번 달라집니다.
Runnable 인터페이스
는@FunctionalInterface
가 선언되어 있는함수형 인터페이스
입니다.람다식
을 이용해서 Runnable 객체를 구현할 수 있습니다.
- Thread 클래스는 run()을 구현하고 있지 않습니다.
Runnable 인터페이스의 run()을 구현
해서 스레드가 할 작업을 지정합니다.
스레드 설정
- Thread의
start()
는 스레드를실행 대기 상태
로 만들어줍니다. - 실행 대기 상태인 스레드는 메인 스레드는
main
, 이외의 스레드는Thread-번호
의 형태로 이름이 지정됩니다.- 스레드에 대해서 디버깅 등 작업을 수행할 때 스레드를 쉽게 식별하기 위해서
setName()
을 통해서 이름을 지정할 수 있습니다.
- 스레드에 대해서 디버깅 등 작업을 수행할 때 스레드를 쉽게 식별하기 위해서
- 스레드는
setPriority()
를 통해서우선순위
를 지정할 수 있습니다.- 우선순위는
1 ~ 10
인 정수이며,우선순위가 클수록(10) 더 많은 작업시간을 할당받습니다.
- 우선순위를 지정하지 않으면
기본값인 5
가 지정됩니다. - Thread 클래스에 선언된 우선순위 상수를 이용할 수 있습니다.
Thread.MAX_PRIORITY
,Thread.MIN_PRIORITY
,Thread.NORM_PRIORITY
- 우선순위는
스레드 간 동기화
동기화
- 공유 자원을 여러 스레드가 동시에 접근할 때 발생할 수 있는 오류를 방지하는 작업입니다.
- 동기화 처리는
synchronized
키워드를 사용하여 블록, 메서드 단위로 수행할 수 있습니다.블록 동기화
:synchronized (객체 이름) { ... }
- 어떤 스레드가 공유 객체에서 작업을 수행하고 있다면, 다른 스레드는 해당 작업이 끝날때까지 객체를 참조할 수 없습니다.
- 공유 객체 이름을 지정해서 공유 객체를 동시 참조하여 발생할 수 있는 에러를 방지합니다.
- 만일 클래스 자신이 공유된다면
this
를 지정합니다.
메서드 동기화
:synchronized returnType 메서드 이름(매개변수...) { ... }
- 어떤 스레드가 해당 메서드를 호출하고 있다면, 다른 스레드는 해당 작업이 끝날때까지 메서드를 호출할 수 없습니다.
스레드 제어
- 동시에 실행되는 스레드 수는 CPU가 몇개인지에 따라 결정됩니다.
- CPU가 1개라면 특정 순간에 실행되는 스레드는 1개입니다.
- 스케줄링에 따라 번갈아가며 스레드들이 작업을 수행하기 때문에 동시에 하는 것처럼 느껴집니다.
스레드 상태
Thread.state
라는 enum 클래스를 통해서 스레드의 상태가 구분되어 있습니다.
NEW
- 스레드 객체는 생성되었지만, 아직 start()가 호출되지 않은 상태
RUNNABLE
- start()가 호출되어서 실행할 수 있는 상태
- RUNNABLE일때 스레드는 JVM의 스케줄링에 의해 실행될 수 있음
BLOCKED
- 실행 대기 상태
- JVM에 의해 RUNNABLE로 변경될 수 있음
WAITING
- 실행 대기 상태
- 다른 스레드에 의해 RUNNABLE로 변경될 수 있음
TIME_WAITING
- 실행 대기 상태
- 일정 시간이 지나야 RUNNABLE로 변경될 수 있음
TERMINATED
- 스레드 실행 종료 상태
스레드 제어 메서드
java.lang.object
에 있습니다.
wait()
- 호출한 스레드는 RUNNABLE --> WAITING
notify()
- WAITING인 스레드 중에서 1개의 스레드만 RUNNABLE로 변경
notifyAll()
- WAITING인 스레드 모두 RUNNABLE로 변경
join()
- 스레드 간 종속관계를 지정
- 실행중인 스레드는 다른 스레드의 join()을 만나면 join()을 호출한 스레드의 작업이 끝날때까지 대기
sleep()
- 호출한 스레드를 지정된 시간동안 TIME_WAITING으로 변경
interrupt()
- RUNNABLE인 스레드들의 실행을 중지
스레드 풀(Thread Pool)
- 스레드의 수가 증가할수록 메모리 사용량이 늘고, 스케줄링 또한 복잡해집니다.
- 스레드 풀은 이러한 난점을 극복하기 위해서
미리 스레드를 생성해놓고 재사용
하는 방식입니다. - 재사용을 통해서 생성, 삭제 비용을 줄일 수 있습니다.
- 스레드 수를 제한하여 스케줄링 오버헤드를 줄일 수 있습니다.
ExecutorService
- 스레드 풀을 지원하는 인터페이스입니다.
Executors
의 메서드를 사용해서 ExecutorService에 스레드 풀을 할당합니다.newFixedThreadPool(int nThreads)
- 매개변수로 받은 수만큼 스레드를 생성하고 관리합니다.
newCachedThreadPool()
- 스레드 풀에 재사용할 수 있는 스레드가 있으면 재사용합니다.
- 스레드가 없으면 스레드를 생성합니다.
- 60초 동안 사용되지 않은 스레드는 삭제합니다.
- 작업 실행
execute(Runnable runnable)
- Runnable을 구현한 객체를 매개변수로 받아 스레드에 할당하고 작업을 수행합니다.
- 스레드 풀 종료
- 스레드 풀을 종료하지 않으면 프로그램이 종료되지 않습니다. 사용했으면 반드시 닫아야 합니다.
shutDown()
- 현재 실행중인 스레드의 작업이 끝나면 스레드 풀을 닫습니다.
shutDownNow()
- 실행중인 스레드의 작업을 즉시 종료하고 스레드 풀을 닫습니다.
'Language | Basic > Java' 카테고리의 다른 글
Java의 Garbage Collection (0) | 2021.05.28 |
---|---|
JVM의 Heap Area (0) | 2021.05.28 |
JVM(Java Virtual Machine)이란 (0) | 2021.05.28 |
Lambda와 함수형 인터페이스 (0) | 2021.05.18 |
Stream API (0) | 2021.05.10 |