12장 쓰레드와 멀티태스킹
12.1 쓰레드(Thread)
(1) 멀티태스킹(multi-tasking)의 개념
- 프로세스: 실행 중인 프로그램의 단위
- 컴퓨터에서 프로그램을 실행하면 적어도 하나 이상의 프로세스가 동작하게됨
- 디스크에 있는 프로그램이 메모리에 적재되어 운영체제의 제어를 받는 상태를 의미함
- 자신만의 자원을 가지기 때문에 프로세스끼리는 서로 독립적
- 멀티태스킹: 여러 개의 작업(태스크)을 동시에 처리함
- 멀티 코어 CPU: 다수의 응용 프로그램을 동시에 병렬처리함
- 싱글 코어 CPU: 운영체제가 응용 프로그램을 병행처리함
- 멀티 프로세싱(multi-processing) / 멀티-쓰레딩(multi-threading)
(2) 쓰레드
- 쓰레드: 프로그램 코드를 이동하면서 실행하는 하나의 제어
- 프로세스에 있는 리소스(resource)를 공유하는 프로그램의 실행 단위
- 단일 프로세스에서 여러 개의 쓰레드가 존재할 수 있음
- 하나의 실행 흐름으로 프로세스의 내부에 존재함
- 하나의 프로세스는 하나 이상의 실행 흐름을 포함하기 때문에 프로세스는 적어도 하나의 쓰레드를 가짐
- 메모리와 파일 등 모든 자원을 프로세스 자원과 공유
→ 프로세스에 비해 필요한 자원이 적음
12.2 자바 쓰레드
(1) 자바 쓰레드
- 자바 가상 기계(JVM)에 의해 스케줄되는 실행 단위의 코드 블럭
- 쓰레드의 생명 주기는 JVM에 의해 관리됨(JVM은 쓰레드 단위로 스케줄링됨)
- JVM과 멀티 쓰레드의 관계: 하나의 JVM은 하나의 자바 응용 프로그램만 실행함
- 자바 응용 프로그램이 시작될 때 JVM이 함께 실행됨
- 자바 응용 프로그램이 종료되면 JVM도 함께 종료됨
- 하나의 응용 프로그램은 하나 이상의 쓰레드로 구성이 가능함
(2) JVM, 자바 응용 프로그램, 쓰레드의 관계
- JVM은 하나의 응용 프로그램만 실행이 가능함 → JVM은 여러 개의 응용 프로그램을 실행할 수 없음
- 하나의 응용 프로그램은 여러 개의 쓰레드를 가질 수 있음
- 두 개의 자바 응용 프로그램이 동시에 실행되려고 하면 각자 두 개의 JVM을 이용함. 응용 프로그램은 서로 소켓을 이용해 통신함
- 각 쓰레드의 쓰레드 코드는 각자의 응용 프로그램 내에 존재함
- JVM이 쓰레드가 몇 개인지, 쓰레드 코드의 위치가 어디인지, 우선 순위는 얼마인지 등을 관리함
12.3 쓰레드 작성
(1) 쓰레드 만들기
- 쓰레드 실행을 위해 개발자가 하는 일
- 쓰레드 코드 작성하기
- JVM에게 쓰레드를 생성하고 쓰레드 코드를 실행하도록 요청하기
- 자바에서 쓰레드를 만드는 방법
- java.lang.Thread 클래스를 이용하기(extends 키워드를 이용해 상속 받음)
- java.lang.Runnable 인터페이스 이용하기(implements 키워드를 이용함)
(2) Thread 클래스의 생성자와 메소드
- 생성자
- Thread()
- Thread(Runnable target)
- Thread(String name)
- Thread(Runnable target, String name)
- 메소드
메소드 | 설명 |
static Thread currentThread() | 현재 실행 중인 쓰레드의 실제 객체를 반환함 |
long getID() | 쓰레드의 ID를 반환함 |
String getName() | 쓰레드의 이름을 반환함 |
int getPriority() | 쓰레드의 우선 순위(1~10)을 반환함 |
void join() | 쓰레드가 죽지 안도록 우선적으로 실행함 |
static void sleep(long 밀리초) | 쓰레드를 멈추게함 |
void start() | 쓰레드를 실행함(run()을 실행함) |
static void yield() | 현재 실행 중인 쓰레드를 멈추고 다른 쓰레드를 실행함 |
(3) Thread 클래스를 이용해 쓰레드 생성하기
- 쓰레드 클래스 작성하기: Thread 클래스 상속 받기(extends Thread). 새 클래스 작성하기
- 쓰레드 코드 작성하기: run()를 반드시 메소드 오버라이딩하기. run() 메소드에서 쓰레드 실행 시작
- 쓰레드 객체 생성하기
- 쓰레드 시작하기: start() 메소드 호출하기(run()이 작동됨)
→ 쓰레드로 작동을 시작함. JVM에 의해 스케줄링 되기 시작함
class 클래스_이름 extends Thread { ① Thread 클래스 상속 받기 public void run() { ② 메소드 오버라이딩하기 } } |
public static void main(String[] args) { 클래스_이름 객체_이름 = new 클래스_이름(); ③ 객체 생성하기 객체_이름.start(); ④ 쓰레드 시작하기 } |
(4) Runnable 인터페이스로 쓰레드 생성하기
- 쓰레드 클래스 작성하기: Runnable 인터페이스를 구현하는 클래스를 작성하기
- 쓰레드 코드 작성하기: run() 메소드를 반드시 오버라이딩 해야함
- 쓰레드 객체 생성하기
- 쓰레드 시작하기: start() 메소드 호출하기
class 클래스_이름 implements Runnable { ① Runnable 인터페이스 구현하기 public void run() { ② 메소드 오버라이딩하기 } } |
public static void main(String[] args) { 클래스_이름 객체_이름 = new 클래스_이름(); ③ 객체 생성하기 객체_이름.start(); ④ 쓰레드 시작하기 } |
12.4 쓰레드 정보
(1) 쓰레드를 사용할 때 주의해야 할 점
- run() 메소드가 종료되면 쓰레드도 종료됨
- 쓰레드가 계속 존재하도록 하려면 run() 메소드의 안에서 무한 루프가 실행되어야 함
- 한 번 종료한 쓰레드는 다시 시작될 수 없음
- 다시 시작하려면 쓰레드 객체를 생성해 다시 쓰레드로 등록해야함
- 한 쓰레드에서 다른 쓰레드를 강제 종료시킬 수 있음
(2) 쓰레드에 대한 정보
필드 | 타입 | 내용 |
쓰레드의 이름 | 문자열 | 쓰레드의 이름으로서 사용자가 지정할 수 있음 |
쓰레드의 ID | 정수 | 쓰레드 고유의 식별자 번호 |
쓰레드의 Program Count | 정수 | 현재 실행 중인 쓰레드 코드의 주소를 나타냄 |
쓰레드의 상태 | 정수 | NEW, RUNNABLE, WAITING, TIMED_WAITING. BLOCK.TERMINATED의 6 가지 중 하나를 나타냄 |
쓰레드의 우선 순위 | 정수 | 쓰레드 스케줄링 시 사용되는 우선 순위 값. 1~10 사이의 값이며 10이 최상위를 나타냄(가장 우선적으로 실행됨) |
쓰레드 그룹 | 정수 | 여러 개의 자바 쓰레드가 하나의 그룹을 형성 할 수 있으며 현재 쓰레드가 속한 그룹을 나타냄 |
쓰레드 레지스터 스택 | 메모리 블록 | 쓰레드가 실행되는 동안의 레지스터의 값을 나타냄 |
- 쓰레드의 6 가지 상태
- NEW: 쓰레드가 생성되었지만 스레드가 아직 실행할 준비가 되지 않은 상태
- RUNNABLE: 쓰레드가 JVM에 의해 실행되고 있거나 실행 준비가 되어 스케줄링을 기다리는 상태
- WAITING: 어떤 Object 객체에서 다른 쓰레드가 notify()나 notifyAll()을 사용해 불러 주기를 기다리고 있는 상태
→ 쓰레드 동기화를 위해서 사용함 - TIME_WAITING: 쓰레드가 sleep(n)의 호출로 인해 n 밀리초 동안 잠을 자고 있는 상태
- BLOCK: 쓰레드가 JVM에 입출력(I/O) 작업을 요청한 상태
- TERMINATED: 쓰레드가 종료한 상태
- 쓰레드의 상태는 JVM이 기록하고 관리함
- 쓰레드의 상태와 생명주기
(3) 쓰레드의 우선 순위와 스케줄링
- 쓰레드의 우선 순위: 최대 = 10, 중간 = 5, 최소 = 1
- 쓰레드의 우선 순위는 setPriority(정수) 메소드를 이용해 변경 가능
- getPriority() 메소드를 이용해 현재 쓰레드의 우선 순위를 알 수 있음
- main() 쓰레드의 우선 순위 값은 초기에 5로 설정됨
- main() 메소드의 쓰레드를 말함. 자바 쓰레드라고 할 수 있음 (JVM에 의해 자동으로 쓰레드화됨)
- 쓰레드는 처음에 부모 쓰레드와 같은 우선 순위를 가지고 만들어짐
- JVM의 쓰레드 스케줄링 정책
- 가장 높은 우선 순위를 가진 쓰레드가 먼저 실행됨
- 같은 우선 순위들 끼리는 순서대로 돌아가면서 실행됨(라운드 로빈)
(4) 쓰레드 종료
- 스스로 종료하기: run() 메소드가 실행이 종료됨
- 다른 쓰레드에서 강제로 어떤 쓰레드를 종료시키기: interrupt() 메소드 사용하기
'기초' 카테고리의 다른 글
[JAVA] 13 - 네트워크 기초 (0) | 2020.05.21 |
---|---|
[JAVA] 12 - 쓰레드 동기화 (0) | 2020.05.21 |
[JAVA] 10 - 파일 입출력 (0) | 2020.05.19 |
[JAVA] 9 - 컬렉션 프레임워크 (0) | 2020.05.18 |
[JAVA] 8 - 추상 클래스, 인터페이스, 패키지 (0) | 2020.05.17 |