JAVA

스레드 생성과 실행 - 스레드 종류

silver-w 2024. 10. 23. 21:45

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이 종료된다.

 

 


출처 : 1https://inf.run/NC7kS

 

김영한의 실전 자바 - 고급 1편, 멀티스레드와 동시성 강의 | 김영한 - 인프런

김영한 | 멀티스레드와 동시성을 기초부터 실무 레벨까지 깊이있게 학습합니다., 국내 개발 분야 누적 수강생 1위, 제대로 만든 김영한의 실전 자바[사진][임베딩 영상]단순히 자바 문법을 안다?

www.inflearn.com