Java의 Thread에 대해 알아보자

wnajsldkf·2022년 11월 14일
0

Java

목록 보기
15/19
post-thumbnail

Thread란 무엇인가?

하나의 프로세스 내에서 실행되는 흐름의 단위를 말한다. 한 프로그램은 하나의 스레드를 가지고 있고, 둘 이상의 스레드를 동시에 실행하는 경우 이 방식을 멀티스레드라고 한다.

ex. 게임할 때 움직이면서 총을 쏘고 싶다. 한번 움직이고 총을 쏘면 효율이 없다. 총을 쏘면서 움직이도록 구현하기 위해 멀티 스레드를 이용하여 많은 양을 한번에 처리하도록 한다.

+) 프로세스란?

프로세스란 실행중인 프로그램을 말한다. 프로그램은 기억장치(SSD)에 존재하며 실행되기를 기다리는 명령어와 정적인 데이터 묶음이다. 이 프로그램을 명령어와 정적 데이터로 메모리에 적재시키면 생명이 있는 프로세스가 된다.

++) Process와 Thread의 차이는 무엇인가?

프로세스는 운영체제로부터 자원을 할당받는 작업 단위이다. 애플리케이션이 하나의 프로세스가 되고, 그 안에서 여러 개의 스레드가 할당 받은 자원을 이용하여 실행 단위로 존재할 수 있다. 즉 스레드는 하나의 프로세스 안에서 여러 실행의 흐름이라고 생각하면 된다.

Java의 Thread란?

자바는 JVM이라는 가상머신에 의해 동작한다. JVM은 운영체제의 역할을 하여, 자바에서 스레드는 JVM에 의해 스케쥴되는 실행 단위 코드 블록이다. JVM에 의해 하나의 프로세스가 발생하는 것이고, main() 안의 실행문들이 하나의 스레드가 된다. 만약 main() 이외의 스레드를 만들려면 Thread 클래스를 상속한다.

JVM은 스레드와 관련된 다음의 정보들을 관리한다.

  • 스레드가 몇 개 존재하는가
  • 스레드로 실행되는 프로그램 코드의 메모리 위치는 어디인가
  • 스레드의 상태는 무엇인가
  • 스레드 우선 순위는 얼마인가

즉, 개발자는 자바 스레드로 작동할 스레드 코드를 작성하며, 스레드 코드가 실행을 시작하도록 JVM에 요청한다. 그러면 JVM은 위의 정보들을 가지고 스레드를 실행시키는 것이다.

멀티스레딩이란?

하나의 프로세스 내에서 여러 스레드를 동시에 실행시키는 방법을 말한다. 웹 서버는 대표적인 멀티 스레드 응용 프로그램이다.

웹 서버로 멀티 스레드 이해하기

하나의 스레드를 사용하여 단일 요청하기

요청이 오면, 쓰레드를 할당하고 쓰레드는 서블릿을 호출하고 서블릿을 작을 후 결과물을 http 응답에 담아 웹에 전달한다.

  • 서블릿은 동적 페이지를 만들 때 사용되는 자바 기반 웹 애플리케이션 프로그래밍을 말한다.

하나의 스레드를 사용하여 다중 요청하기

프로세스는 순서대로 요청을 처리한다.

  1. 요청 1이 오면 하나의 스레드를 할당하고, 요청2가 오면 요청1이 끝날 때까지 기다려야 한다.
  2. 스레드 처리 중 시간이 오래 걸려 처리 지연이 발생한다.
  3. 요청 2는 스레드 대기 상태로 기다리다 타임 아웃 상태가 오고 결국 2번 요청은 죽게 되어 제대로된 수행이 어려워진다.

이 문제를 해결하려면 요청마다 스레드를 생성하는 방법이 있다.

물론 요청마다 스레드를 생성하는 것은 장단점이 있다. 장점은 위의 예시처럼 동시 요청 처리가 가능하다. 다만 스레드 생성 비용은 비싸기 때문에 요청마다 스레드를 생성하면 컨텍스트 스위칭 비용이 발생하여 응답 속도가 느려질 것이다.

  • 컨텍스트 스위칭 비용은 스레드가 여러 개일 때 코어 하나가 스레드를 실행하고 다음 것을 시행할 때, 전환할 때 발생하는 값을 말한다.

이를 극복할 수 있는 방법이 바로 스레드 풀이다! 우선 오늘은 이런 것이 있구나 라고만 잡고 스레드 풀에 대해서는 다음에 더 알아보겠다.

장점

  • 시스템 자원 소모 감소
    • 프로세스를 생성하여 자원을 할당하는 요청이 줄어들기 때문에 자원을 효율적으로 관리할 수 있다.
  • 시스템 처리량 증가
    • 스레드 사이 데이터를 주고 받는 것이 간단해지고 시스템 자원 소모가 줄어들게 된다.
    • 스레드 사이의 작업량이 작아 Context Switching이 빠르다.
  • 간단 통신 방법으로 프로그램 응답 시간을 단축
    • 스레드는 프로세스 내의 Stack 영역을 제외하고 모든 영역을 공유하기 때문에 통신 부담이 적다.

단점

  • 주의 깊은 설계가 필요하며, 디버깅이 까다롭다.
  • 서로 자원을 소모하다 충돌이 일어날 수 있다.
  • 하나의 스레드에 문제가 발생하면 전체 프로세스가 영향을 받을 수 있다.

스레드의 생명주기

  1. New(객체 생성)

    스레드가 만들어진 상태로 아직 start() 메서드가 호출되지 않은 상태이다.

  2. Runnable(준비 상태)

    • 스레드가 실행되기 위한 준비 단계이다.
    • start() 메서드를 호출하면 run() 메서드에 설정된 스레드가 Runnable 상태가 된다.
  3. Running(실행 상태)

    • Runnable(준비 상태)에 있는 스레드 중 우선 순위를 가진 스레드가 결정되면
    • JVM이 자동으로 run() 메서드를 호출하여 스레드가 Running 상태로 진입한다.
  4. Terminated(실행 종료)

    • Running 상태에서 스레드가 모두 실행되고 난 후 완료 상태이다.
    • run() 메서드가 완료되면 스레드가 종료되고, 스레드는 다시 시작할 수 없다.
  5. Blocked(지연 상태)

    • 객체의 Lock이 풀릴 때까지 기다리는 상태이다.
      • wait() 메서드에 의해 Blocked 상태가 된 스레드는 notify() 메서드가 호출되면 Runnable 상태가 된다.
      • sleep(시간) 메서드는 Blocked 상태가 된 스레드를 지정된 시간이 지나면 Runnable 상태가 되도록 한다.

스레드 구현

  • Thread 클래스 상속
  • Runnable 인터페이스 구현

Runnable 인터페이스를 구현하는 것을 추천한다. Thread 클래스를 상속받으면 다른 클래스를 상속받지 못한다. 또한 Runnable을 구현하면 재사용성이 높고 코드의 일관성을 유지할 수 있으므로 더 객체지향적인 방법이다.

Runnable 인터페이스 구현 예제

실행되면 string 값을 출력하는 스레드를 만들었다.

public class ThreadExample {
    public static void main(String[] args) {
        Runnable r1 = new MyThread("*");
        Runnable r2 = new MyThread("!");
        Runnable r3 = new MyThread("&");

        Thread t1 = new Thread(r1);
        Thread t2 = new Thread(r2);
        Thread t3 = new Thread(r3);
        t1.start();
        t2.start();
        t3.start();
        System.out.println("종료");
    }

    static class MyThread implements Runnable {
        private String string;
        public MyThread(String s) {
            this.string = s;
        }

        @Override
        public void run() {
            System.out.println(string);
        }
    }
}

new로 스레드를 생성(New)하고, start() 메서드가 호출되면 스레드가 실행되기 위한 준비 단계(Runnable)가 된다. run() 메서드를 호출하여 스레드를 실행(Running)한다. run() 메서드가 종료되면 스레드는 실행을 종료(Terminated)한다.

실행 결과는 ! → * → 종료 → &로 출력되기도 하고, 종료 → * → & → ! 로 출력되기도 한다.

main 메서드에 의해 메인 스레드가 실행되며, new Thread()로 스레드 객체를 3개 생성하여 총 4개의 스레드가 동시에 실행되기 때문이다.

다음 시간에는 스레드를 사용하는 방법을 코드와 함께 더 살펴보겠다.

Ref

profile
https://mywnajsldkf.tistory.com -> 이사 중

0개의 댓글