스레드 생성과 실행

Walter Mitty·2025년 4월 4일
0

개인공부

목록 보기
45/51

들어가며,

본격 스레드 진입 전 먼저 기초를 알아보면

  • 메서드 영역(Method Area) : 메서드 영역을 프로그램을 실행하는데 필요한 공통 데이터를 관리
    (이 영역은 프로그램 모든 영역에서 공유한다.)
    • 클래스 정보 - 클래스의 실행 코드(바이트 코드), 필드, 메서드와 생성자 코드등...
    • static 영역 - static 변수들 보관
    • 런타임 상수 풀 - 프로그램을 실행하는데 필요한 공통 리터럴 상수를 보관

  • 스택 영역(Stack Area)
    • 자바 실행 시 하나의 실행 스택이 생성된다.
    • 각 스택 프레임은 지역 변수, 중간 연산 결과, 메서드 호출 정보 등을 포함
      • 스택 프레임이란 위 이미지에서 스택 영역에 쌓이는네모 박스가 하나의 스택 프레임이다. 메서드를 호출할 때 마다 하나의 스택 프레임이 쌓이고 메서드 종료시 해당 스택 프레임이 제거된다.
  • 힙 영역(Heap Area)
    • 객체(인스턴스)와 배열이 생성되는 영역으로, 가비지 컬렉션(GC)이 이루어지는 주요 영역이며, 더 이상 참조되지 않는 객체는 GC에 의해 제거된다.

참고:
더 정확히 말하자면 스택 영역은 각 스레드 별로 하나의 실생 스택이 생성되는데,
따라서 스레드 수 만큼 스택이 생성된다.
스레드를 추가하면 그만큼 스택도 스레드 수 만큼 증가한다.


스레드 생성

스레드를 만들 때는 Thread 클래스를 상속 받는 방법과,
Runnable 인터페이스를 구현하는 방법이 있다.

public class HelloThread extends Thread {

    public void run() {
        System.out.println(Thread.currentThread().getName() + ": run()");
    }
}
public class HelloThreadMain {
    public static void main(String[] args) {
        System.out.println(Thread.currentThread().getName() + ": main() start"); // main 이라는 스레드가 떠서 메인 메서드인 sout 내용을 실행

        HelloThread helloThread = new HelloThread();
        System.out.println(Thread.currentThread().getName() + ": start() 호출 전");
        helloThread.start(); // helloThread.run(); 을 호출하면 안된다! start로 해야 별도의 스레드에서 run()이 실행
        System.out.println(Thread.currentThread().getName() + ": start() 호출 후");

        System.out.println(Thread.currentThread().getName() + ": main() end");

    }
}

RUN

main: main() start
main: start() 호출 전
main: start() 호출 후
main: main() end
Thread-0: run()

Process finished with exit code 0

스레드 생성 후

  • HelloThread 스레드 객체를 생성한 다음 start() 메서드 호출시 자바는 스레드를 위한 별도의 스택 공간을 할당
  • 스레드 객체를 생성하고 반드시 start()를 호출해야 스택 공간을 할당 받고 스레드가 작동한다. 즉 별도의 스레드에서 run()이 실행된다는 뜻
  • 스레드에 이름을 주지 않으면 자바는 스레드에 Thread-0,Thread-1과 같은 임의의 이름을 부여
  • Thread-0 스레드가 사용할 전용 스택 공간이 마련됨
  • Thread-0 스레드는 run() 메서드의 스택 프레임을 스택에 올리면서 run() 메서드를 시작

스레드를 공부하며 이 과정을 실제 손으로 그려보는 것도 추천한다.

main 스레드

  • HelloThread 클래스 인스턴스 생성 (이때 스레드에 이름 안 붙이면 자바가 임의 이름 부여)
  • start() 를 통해 Thread-0 스레드의 실행 스택 공간이 할당받았다.
  • start()를 호출해서 Thread-0 스레드가 시작되면서 Thread-0 스레드가run()을 실행
  • 여기서 main 스레드는 다른 스레드(Thread-0 등)에게 일을 시작하라고 지시만 하고 start() 메서드를 빠져나온다.
  • 그리고 main 스레드가 할 일을 한다.

그래서 가끔 출력된 것을 보면 순서가 바뀌어있는 경우가 있다.

// main 스레드가 빨리 실행된 경우
main: main() start
main: start() 호출 전
main: start() 호출 후
main: main() end
Thread-0: run()

// Thread-0 스레드가 빨리 실행된 경우
main: main() start
main: start() 호출 전
Thread-0: run()
main: start() 호출 후
main: main() end

Thread-0 스레드

  • start()를 호출하는 스레드도 전무 main 스레드고,
    Thread-0은 HelloThread에 있는 run()을 실행시키는 것이다.

만약 CPU 코어가 2개라면 main과 Thread-0을 동시에 실행 시킬 수 있다.
또 하나의 CPU 코어에 시간을 나누어 실행될 수도 있다.
한 스레드가 얼마나 오랜기간 실행되는지도 보장하지 않기 때문에
한 스레드가 먼저 다 수행된 다음에 다른 스레드가 수행될 수도 있고, 둘이 완전히 번갈아 가면서 수행되는 경우도 있다.

스레드는 동시에 실행되기 때문에 스레드 간에 실행 순서나 기간을 보장하지 않는다.
이것이 멀티스레드..!

0개의 댓글