• 티스토리 홈
starryeye
  • 프로필사진
    starryeye
    • 분류 전체보기 (189)
      • C++ (17)
      • Java (24)
      • OOP (5)
      • Spring Reactive Stack (12)
        • Reactive Streams (3)
        • Netty (4)
        • Reactor (1)
        • Webflux (3)
        • DB, Cache 연동 (1)
      • Spring (90)
        • Core (17)
        • MVC (33)
        • Client (2)
        • Security (4)
        • DB, Cache 연동 (33)
      • DataBase (12)
        • RDBMS (2)
        • NoSQL (10)
      • Message Broker (6)
      • Web (4)
      • Network (4)
      • 대규모 시스템 설계 (15)
  • 방문자 수
    • 전체:
    • 오늘:
    • 어제:
  • 최근 댓글
      등록된 댓글이 없습니다.
    • 최근 공지
        등록된 공지가 없습니다.
      # Home
      # 공지사항
      #
      # 태그
      # 검색결과
      # 방명록
      • [Java 정리] Thread 3
        2022년 08월 19일
        • starryeye
        • 작성자
        • 2022.08.19.:20
        반응형

        이미 알던 지식이지만, 기본으로 돌아가서.. Java의 관점에서 한번 정리해보자.

         

        쓰레드의 실행 제어 메서드

         

        쓰레드 상태를 다시 한번 보고 들어가자..

        상태 설명
        NEW 쓰레드가 생성되고 아직 start()가 호출되지 않은 상태
        RUNNABLE 실행 중 또는 실행 가능한(실행 대기) 상태
        BLOCKED 동기화 블럭에 의해 일시정지된 상태 (lock이 풀릴 때까지 기다리는 상태)
        WAITING 쓰레드의 작업이 종료되지는 않았지만 실행가능하지 않은 일시정지 상태이다.
        TIMED_WAITING WAITING와 동일하나 일시정지 시간이 지정된 경우의 일시정지 상태이다.
        TERMINATED 쓰레드의 작업이 종료된 상태

         

         

        sleep()

        일정 시간 동안 쓰레드를 멈추게 한다.

         

        public static native void sleep(long millis)
        public static void sleep(long millis, int nanos)

         

        1. sleep()에 의해 일시정지 상태가 된 쓰레드는 지정 시간이 다 되면, 잠에서 깨어나 실행 대기 상태가 된다.

        2. 도중에 interrupt()가 호출되면 InterruptedException 예외가 발생하며, 잠에서 깨어나 실행 대기 상태가 된다.

        3. 항상 현재 실행 중인 쓰레드에 대해 작동한다.

        (A 쓰레드에서 B쓰레드의 참조변수 활용하여 sleep을 호출해도 호출한 A 쓰레드가 sleep된다.)

        (-> static 메서드이지만, native 메서드로 호출한 쓰레드가 일시정지 상태가 됨)

        (-> static 메서드니까 쓰레드 구분이 없을것 같은데? 라는 생각은 native 메서드로 row 레벨에서 구분된다고 이해)

        4. InterruptedException은 체크 예외 이므로 try-catch 구문 혹은 throws를 해줘야한다.

         

        예시

        void delay(long millis) {
            try {
                Thread.sleep(millis); //Thread 클래스의 static 메서드인 sleep 호출
            } catch(InterruptedException e) {
                //Interrupt()가 호출될 경우
            }
        }

         

         

        interrupt()와 interrupted(), isInterrupted()

        public void interrupt()
        public static boolean interrupted()
        public boolean isInterrupted()

         

        interrupt()는 쓰레드에게 작업을 멈추라고 요청한다.

        - 쓰레드의 intterrupted 상태(인스턴스 변수)를 바꾼다.

         

        interrupted()는 쓰레드의 interrupt()가 호출되었는지 알려준다.

        - 호출되지 않았다면 false 반환

        - 호출되었다면 true 반환, false로 다시 초기화

         

        isInterrupted()는 쓰레드의 interrupt()가 호출되었는지 알려주지만, 다시 false로 초기화 하지 않는다.

        (단순 현재의 interrupted 상태를 반환만 한다.)

         

         

        쓰레드가 sleep(), wait(), join()에 의해 일시정지 상태(WAITING)에 있을 때, 해당 쓰레드에 대해

        interrupt()를 호출하면, sleep(), wait(), join()에서 InterruptedException 예외가 발생하고

        쓰레드는 실행 대기 상태(RUNNABLE)로 바뀐다.

        (멈춰있던 쓰레드를 깨워서 실행가능한 상태로 만드는 것)

         

        예시

        Thread th = new Thread();
        th.start();
        
        ...
        
        th.interrupt();
        
        class MyThread extends Thread {
            public void run() {
                while(!interrupted()) { 
                    ... //인터럽트 발생 전까지 계속 돈다.
                }
            }
        }

         

         

        suspend(), resume(), stop()

         

        suspend()는 sleep()처럼 쓰레드를 일시정지 상태로 만든다.

         

        resume()은 suspend()에 의해 일시정지된 쓰레드를 다시 실행대기 상태로 변경 시킨다.

         

        stop()은 호출되는 즉시 쓰레드가 종료된다.

         

        Java API문서에 위 세가지의 메서드는 모두 Deprecated이다.

        쓰레드의 실행을 제어하기 쉬운 메서드이지만, 교착상태를 유발하기 좋은 메서드이므로 사용을 권장하지 않는다.

         

         

        yield()

         

        yield()는 쓰레드 자신에게 주어진 실행시간을 다음 차례의 쓰레드에게 양보한다.

        (yield()와 interrupt()를 적절히 사용하면, 프로그램의 응답성을 높이고 효율적인 실행이 가능해진다.)

        public static native void yield()

         

        예시

        //class MyThread implements Runnable 
        
        Thread th;
        boolean checked = true;
        
        public MyThread(String name) {
            th = new Thread(this, name); // Thread(Runnable r, String name)
        }
        
        public void check() {
            checked = false;
            
            //Thread.currentThread().interrupt(); 이렇게 하면 호출한 쓰레드가 interrupt
            th.interrupt();
        }
        
        public void run() {
            while(true) {
                if(checked) {
                    try {
                        Thread.sleep(10000);
                    } catch(InterruptedException e) {}
                    
                }else {
                    Thread.yield();
                }
            }
        }

        해당 쓰레드 동작 로직은 while문을 끊임 없이 도는 것이다.

        checked라는 인스턴스 변수가 true라면 sleep()을 수행하고 false라면 yield() 메서드를 호출한다.

         

        1. 여기서..

        else 부분이 없다고 생각해보자..

        checked 인스턴수 변수가 false라면 아무 의미 없이 while 구문을 돌 것이다...

        이런 상태를 바쁜 대기상태(busy-waiting)라고 한다.

         

        이는 좋지 않은 코드이며, 위 코드처럼 else로 yeild() 메서드를 호출해주도록 하자..

        남은 실행시간을 while문에서 낭비하지 않고 다른 쓰레드에게 양보(yeild) 해주도록 하자.

        -> 응답성 향상

         

        2. check()라는 메서드가 호출되면 interrupt() 메서드를 호출해주는 이유는...

        쓰레드가 sleep이 호출되어 일시정지 상태에 있을 때,

        interrupt()메서드로 인해 InterruptedException 예외가 호출 될 것이고..

        바로 yield가 호출 될 것이다.

        -> 응답성 향상

        (interrupt()가 없다면 sleep이 다끝나고, 실행대기시간을 기다린후.. yield가 호출 될 것이다..)

         

        <참고>

        코어 수 보다 많은 멀티쓰레드 환경에서 sleep은 일시정지 상태기 때문에 일시정지 상태일때

        다른 쓰레드가 RUNNABLE로 수행되고 있을 것이다..

        그래서 다른쓰레드 수행되니까 yield의 의미가 없다고 생각하지말고..

        sleep이 아닌 다른 로직을 계속 돌려서..

        (그러면 해당 로직에서 InterruptedException 처리 말고 다르게 처리가 필요하긴함)

        RUNNABLE상태에서 점유 한다고 생각하자..

        -> yield()를 호출해주는게 의미가 있다

         

         

         

        join()

        쓰레드 자신이 하던 작업을 잠시 멈추고 다른 쓰레드가 지정된 시간동안 작업을 수행하도록 할 때 사용한다.

        쓰레드 자신은 다른 쓰레드가 작업을 끝낼때까지 기다림.

         

        보통 쓰레드 A가 특정 작업을 하기전에 B쓰레드가 뭔가를 해줘야 특정 작업을 할 수 있을 때..

        B.join()을 불러준다.

        B가 일시정지 상태에 있을 수도 있으니.. join() 전에 interrupt()도 불러준다..

         

         

         

        반응형

        'Java' 카테고리의 다른 글

        [Java 정리] Thread 5  (0) 2022.08.22
        [Java 정리] Thread 4  (0) 2022.08.22
        [Java 정리] Thread 2  (0) 2022.08.13
        [Java 정리] Thread 1  (0) 2022.08.13
        [Java 정리] String, final, Immutable  (0) 2022.08.05
        다음글
        다음 글이 없습니다.
        이전글
        이전 글이 없습니다.
        댓글
      조회된 결과가 없습니다.
      스킨 업데이트 안내
      현재 이용하고 계신 스킨의 버전보다 더 높은 최신 버전이 감지 되었습니다. 최신버전 스킨 파일을 다운로드 받을 수 있는 페이지로 이동하시겠습니까?
      ("아니오" 를 선택할 시 30일 동안 최신 버전이 감지되어도 모달 창이 표시되지 않습니다.)
      목차
      표시할 목차가 없습니다.
        • 안녕하세요
        • 감사해요
        • 잘있어요

        티스토리툴바