김영한의 실전 자바 - 고급 1편(스레드 생명주기, join, interrupt, yield)

2025. 1. 4. 01:03·김영한의 실전 자바 - 고급 1편

3. 스레드 제어와 생명 주기1


  • 각 상태에 대해서 설명하시오
     
    • New (새로운 상태): 스레드가 생성되었으나 아직 시작되지 않은 상태.
    • Runnable (실행 가능 상태): 스레드가 실행 중이거나 실행될 준비가 된 상태.
    • 일시 중지 상태들
      • (Suspended States) Blocked (차단 상태): 스레드가 동기화 락을 기다리는 상태.
      • Waiting (대기 상태): 스레드가 무기한으로 다른 스레드의 작업을 기다리는 상태.
      • Timed Waiting (시간 제한 대기 상태): 스레드가 일정 시간 동안 다른 스레드의 작업을 기다리는 상태.
    • Terminated (종료 상태): 스레드의 실행이 완료된 상태.

 

  • Runnable 인터페이스의 run() 메서드를 구현할 때 InterruptedException 체크 예외를 밖으로 던질 수 없 는 이유는?
    • 체크 예외
      • 부모 메서드가 체크 예외를 던지지 않는 경우, 재정의된 자식 메서드도 체크 예외를 던질 수 없다.
        -> Runnable의 run()이 throw가 없는 이유는 try catch로 예외 처리를 강제하기 위함
      • 자식 메서드는 부모 메서드가 던질 수 있는 체크 예외의 하위 타입만 던질 수 있다.
    • 언체크(런타임) 예외
      • 예외 처리를 강제하지 않으므로 상관없이 던질 수 있다.

 

  • Join 함수를 어떤 경우에 사용하는가?
    • join 함수는 특정 스레드가 완료될 때 까지 기다려야 하는 경우에 사용할 수 있다.
    • sleep을 하거나 while()로 특정 스레드가 끝날 때 까지를 찾는 방법도 있겠지만 비효율적이기 때문에 join 함수를 통해서 특정 스레드가 완료됨을 간편하게 기다릴 수 있다.

 

  • Join 함수를 사용하는 경우 join 함수를 호출하는 스레드와 join 함수 호출을 당하는 스레드의 스레드 상태 변화 플로우는 어떻게 되는가
    • join 함수를 호출하는 스레드는 join 함수 호출 후 Runnable에서 Waiting 상태로 변하게 된다.
    • join 함수 호출을 당하는 스레드는 Runnable에서 결국 Terminated가 된다.
    • 그 이후 join 함수를 호출하는 스레드는 Waiting에서 다시 Runnable 상태로 변한다.

 

  • join 함수의 단점은 무엇이며 그것을 보완하는 방안은 무엇인가?
    • join 함수를 호출한 경우 특정 스레드가 종료될 때까지 무한정 기다려야한다는 단점이 있다.
    • 따라서 join(ms)로 인자를 넣어서 호출하는 경우 특정 시간까지만 기다리고 그 이후에는 다시 Runnable로 변해서 처리를 이어갈 수 있다.

 

 

4. 스레드 제어와 생명 주기2


  • 실행중인 특정 스레드를 멈추게 하고 싶을 때 flag를 지정 후 flag를 검사를 통해 스레드를 멈추게 할 수 있다. 이 방법의 단점은 무엇이며 이를 해결하기 위해 무엇을 도입할 수 있는가?
    • flag를 지정해 검사를 하는 경우는 검사하는 해당 로직에서만 특정 스레드를 멈추게 할지 아닐지를 판단하게 되기 때문에 그 외의 작업시에는 멈추게 할 수가 없음.
    • thread.interrupt() 함수를 호출하면 sleep과 같은 오래 걸리는 작업에 interrupt exception을 발생시켜 빠져나오게 함.
    • 또한, flag로 작업을 진행할지 말지를 결정하지 않고 Thread.currentThread().isInterrupt()와 같은 방법으로 interrupt가 걸렸는지를 확인 할 수도 있다.

 

  • 인터럽트를 확인하는 동시에 인터럽트가 true이면 false로 바꿔주는 함수가 무엇이며 이런 함수를 왜 사용하는가?
    • Thread.interrupted()
    • sleep 과 같은 함수가 없으면 interrupt를 받아도 interrupt가 발생하지 않으며, 원하지 않는 위치에서 interrupt가 발생할 수도 있다.
    • 따라서 interrupted 함수로 interrupt를 받았는지 확인을 하고 바로 interrupt는 false로 돌려준다.

 

  • 인터럽트는 왜 sleep과 같은 함수에서만 예외를 발생시킬까?
    • 인터럽트는 sleep, wait, join과 같이 대기해야하는 함수에서 예외를 발생시킨다.
      • 인터럽트는 Waiting, Timed-Waiting 과 같은 상태에서 Interrupted Exception을 발생시켜 Runnable 상태로 깨워나게 해줌.
      • Runnable, Blocked 상태에서는 Interrupted Exception을 발생시키지 않고 Interrupt flag만 true로 바꿔줌.
    • 스레드의 무한 대기를 방지할 수 있고, 인터럽트 발생시 즉시 반응할 수 있게 하기 위해서.
    • 따라서, sleep, wait, join과 같은 함수는 InterruptedException이라는 체크 예외가 강제되어 try ~ catch와 같은 구문으로 처리를 해줘야 함.
    • 체크 예외는 IOException, SQLException, FileNotFoundException과 같이 외부 자원과 상호 작용 시 발생할 수 있는 문제로 개발자가 통제 할 수 없는 외부 요인에 대해 미리 강제로 처리하도록 함.
    • 반대로 언체크드 예외는 NullPointerException, ArrayIndexOutOfBoundsException과 같은 예외들이 있음.

 

  • yield 함수에 대해 설명하고 sleep 함수를 호출했을 때와 대비해서 Thread의 상태가 어떻게 변경되는가?
    • yield 함수는 CPU 자원을 양보한다는 의미로 만약 스레드 큐에 실행되야 할 스레드가 있다면 그 스레드에게 지금 자신이 사용하고 있는 자원을 양보한다는 의미임.
    • sleep 함수의 경우 스레드의 상태가 Runnable -> Waiting -> Runnable로 변하는 판면 yield 함수의 경우 스레드의 상태가 Runnable(start) -> Runnable(ready) -> Runnable(start)가 됨.
    • 즉, yield의 경우에는 못해도 실행가능한 큐에 들어가므로 양보할 스레드가 없으면 바로 실행 됨.
    • Runnable(ready)와 Waiting의 차이가 여기서 드러나는데 Runnable(ready)는 즉시 실행 가능한 큐에 들어가는 반면 Waiting은 기다림이 끝나고 나서 다시 Runnable(ready)로 들어가는 차이가 있음.

 

  • 프린터기 에제에서 yield 함수는 어느 경우에 사용이 될 수 있나?
    • 예를 들어 프린터 예제에서 프린터는 작업이 왔을 경우 작업물을 출력하기 때문에 작업이 왔는지를 무한정 체크하는 로직이 존재함.
    • 작업이 왔는지를 무한정 체크하는 작업은 계속해서 CPU 자원을 소모하기 때문에 매우 자원 소모가 큰 작업임.
    • 따라서, 할당된 작업이 없는 경우 yield 함수를 불러 다른 스레드에게 자원을 양보하고 나서 다시 할당받고 작업이 왔는지를 체크하는 방법이 자원 효율적임

'김영한의 실전 자바 - 고급 1편' 카테고리의 다른 글

김영한의 실전 자바 - 고급 1편(동시성 컬렉션)  (0) 2025.01.11
김영한의 실전 자바 - 고급 1편(CAS)  (1) 2025.01.11
김영한의 실전 자바 - 고급 1편(생산자 소비자 문제: Object - wait/notify, ReentarantLock - await/signal, BlockingQueue)  (1) 2025.01.08
김영한의 실전 자바 - 고급 1편(volatile, synchronized, LockSupport, ReentrantLock)  (1) 2025.01.05
김영한의 실전 자바 - 고급 1편(프로세스, 스레드)  (3) 2025.01.02
'김영한의 실전 자바 - 고급 1편' 카테고리의 다른 글
  • 김영한의 실전 자바 - 고급 1편(CAS)
  • 김영한의 실전 자바 - 고급 1편(생산자 소비자 문제: Object - wait/notify, ReentarantLock - await/signal, BlockingQueue)
  • 김영한의 실전 자바 - 고급 1편(volatile, synchronized, LockSupport, ReentrantLock)
  • 김영한의 실전 자바 - 고급 1편(프로세스, 스레드)
5jyan5
5jyan5
  • 5jyan5
    jyan
    5jyan5
  • 전체
    오늘
    어제
    • 분류 전체보기 (242)
      • 김영한의 스프링 핵심 원리(기본편) (8)
      • 김영한의 스프링 핵심 원리 - 고급편 (11)
      • 김영한의 스프링 MVC 1편 (1)
      • 김영한의 스프링 DB 1편 (3)
      • 김영한의 스프링 MVC 2편 (3)
      • 김영한의 ORM 표준 JPA 프로그래밍(기본편) (9)
      • 김영한의 스프링 부트와 JPA 활용2 (2)
      • 김영한의 실전 자바 - 중급 1편 (1)
      • 김영한의 실전 자바 - 고급 1편 (9)
      • 김영한의 실전 자바 - 고급 2편 (9)
      • Readable Code: 읽기 좋은 코드를 작성.. (2)
      • 김영한의 실전 자바 - 고급 3편 (9)
      • CKA (118)
      • 개발 (37)
      • 경제 (4)
      • 리뷰 (1)
      • 정보 (2)
  • 블로그 메뉴

    • 링크

    • 공지사항

    • 인기 글

    • 태그

      Thread
      락
      cglib
      프록시
      버퍼
      @args
      typequery
      김영한
      고급
      Target
      프록시 팩토리
      @discriminatorcolumn
      빈 후처리기
      단방향 맵핑
      gesingleresult
      @discriminatorvalue
      log trace
      자바
      WAS
      양방향 맵핑
      jpq
      JPQL
      페치 조인
      reentarantlock
      조회 성능 최적화
      jdk 동적 프록시
      @within
      requset scope
      스레드
      hibernate5module
    • 최근 댓글

    • 최근 글

    • hELLO· Designed By정상우.v4.10.2
    5jyan5
    김영한의 실전 자바 - 고급 1편(스레드 생명주기, join, interrupt, yield)
    상단으로

    티스토리툴바