1. 자바 메모리
메서드 영역
- 프로그램을 실행하는데 필요한 공통 데이터를 관리
- 클래스 정보
- static 영역
- 런타임 상수 풀
스택 영역
- 자바 실행 시, 하나의 실행 스택이 생성
- 스택 프레임 : 메서드를 호출할 때 마다 하나의 스택프레임이 쌓이고, 메서드가 종료되면 해당 스택 프레임이 제거
- 스레드 별로 하나의 실행 스택이 생성된다. 따라서 스레드 수 만큼 스택이 생성
- 지역 변수, 중간 연산 결과, 메서드 호출 정보
힙 영역
- 객체(인스턴스)와 배열이 생성, GC가 이루어지는 영역
2. 멀티 스레드
public class HelloThread extends Thread {
@Override
public void run() {
System.out.println(Thread.currentThread().getName() + ": run()");
}
}
package thread.start;
public class HelloThreadMain {
public static void main(String[] args) {
System.out.println(Thread.currentThread().getName() + " start");
HelloThread helloThread = new HelloThread();
System.out.println(Thread.currentThread().getName() + "start 호출 전");
helloThread.start();
System.out.println(Thread.currentThread().getName() + "start 호출 후");
System.out.println(Thread.currentThread().getName() + " end");
}
}
위 코드의 main스레드는 main 전용 스택 공간을 할당받아 main() 스택 프레임을 올린다.
thread-0스레드는 start()메서드에 의해 thread-0 전용 스택 공간을 할당받아 run() 스택 프레임을 올린다.
※ Thread의 start()
- main 스레드와 별개의 thread-0의 별도 스택 공간을 만들어준다, 스레드를 실행시키는 특별한 메서드.
- 스택프레임이 따로 생긴 시점에 this 는 스택프레임을 가르키는 참조값을 받는다.
- main 스레드에서 절대 run()을 직접적으로 호출하면 안된다.
helloThread.start()를 실행하는 순간 main스레드는 thread-0에게 "run()을 실행해" 라고 지시만 하고
thread-0의 run()의 완료를 기다려주지 않는다. 그러므로 main 스레드의 작업과 thread-0의 작업이 별개로 이루어진다
그러므로, helloThread.start()로 호출되는 thread의 run()은 메인메서드가 끝나고 완료가 될수도 있고, 끝나기 전에 완료될 수도 있다. 실행 순서가 보장이 안됨.
한번에 둘 이상의 스레드가 실행되어 스택 프레임을 각각 쌓아올리는 걸 "멀티 스레드"라고 한다
§ 만약 메인메서드에서 start()가 아니라 run()을 실행하면?
main 스레드가 helloThread라는 객체를 만들기만 하고 run()을 직접적으로 호출한다.
-> thread-0이 스택 영역이 만들어지지 않고, 메인스레드의 스택영역에 스택프레임에 다 처리가 된다.
-> 멀티스레드가 되지 않음
3. 데몬 스레드
스레드는 사용자(user) 스레드(일반적)와 데몬(daemon) 스레드 2가지 종류가 있다.
- 사용자 스레드 (주요)
- 프로그램의 주요 작업을 수행하며, 작업이 완료될 때까지 실행. 완료되면 JVM 종료(각 유저스레드의 스택 영역의 스택 프레임이 다 완료가 되어야 종료된다)
- 데몬 스레드 (보조)
- 사용자에게 보이지 않음. 백그라운드에서 보조적인 작업을 수행, 작업 완료 상관없이 user스레드가 종료되면 자동으로 종료됨. 예를들어 사용하지 않는 파일이나 메모리를 정리하는 작업
// user Thread
public static void main(String[] args) {
System.out.println(Thread.currentThread().getName() + "메인 start");
DaemonThread daemonThread = new DaemonThread();
daemonThread.setDaemon(true); // 데몬 스레드 여부
daemonThread.start();
System.out.println(Thread.currentThread().getName() + "메인 end");
}
// daemon Thread
static class DaemonThread extends Thread { // 10초간 유휴하는 스레드
@Override
public void run() {
System.out.println(Thread.currentThread().getName() + " : run()");
try {
Thread.sleep(10_000);
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
System.out.println(Thread.currentThread().getName() + " : run()");
}
}
- daemonThread.setDaemon(true) 으로 데몬 스레드를 설정할 수 있다.
: 데몬스레드는 메서드 완료 여부 상관없이 user Thread의 작업이 끝나면 자동으로 끝나므로, 10초간 유휴하지 않고 main 스레드가 끝나자마자 바로 JVM이 종료된다.
김영한의 실전 자바 - 고급 1편, 멀티스레드와 동시성 강의 | 김영한 - 인프런
김영한 | 멀티스레드와 동시성을 기초부터 실무 레벨까지 깊이있게 학습합니다., 국내 개발 분야 누적 수강생 1위, 제대로 만든 김영한의 실전 자바[사진][임베딩 영상]단순히 자바 문법을 안다?
www.inflearn.com
'JAVA' 카테고리의 다른 글
API - SimpleDateFormat (날짜 형식으로 포맷) (0) | 2024.10.28 |
---|---|
스레드 생성과 실행 - Runnable (0) | 2024.10.23 |
Context switching와 스레드작업 종류(CPU-bound tasks, I/O-bound tasks) (0) | 2024.10.21 |
(스레드) Thread와 Scheduling (0) | 2024.10.21 |
프로세스와 스레드 (0) | 2024.10.21 |