스 레 드 인 터 럽 트

6997 단어 자바
작업 과 스 레 드 의 시작 은 매우 쉽다.대부분의 경우 우 리 는 그것들 을 끝 날 때 까지 운행 시 키 거나 스스로 멈 추 게 한다.그러나 가끔 우 리 는 작업 이나 스 레 드 를 미리 끝내 고 싶 습 니 다. 사용자 가 작업 을 취소 하거나 응용 프로그램 이 빠르게 닫 혀 야 하기 때 문 일 수도 있 습 니 다. 작업 과 스 레 드 를 안정 시 키 고 빠 르 고 신뢰성 있 게 멈 추 는 것 은 쉬 운 일이 아 닙 니 다.자바 의 Thread 류 는 우리 에 게 stop(), suspend() 등 스 레 드 를 끊 는 방법 을 제공 하 였 으 나, 안전 문제 로 인해 현재 모두 폐기 되 었 다.자바 는 스 레 드 를 중단 하 는 안전 한 방법 을 제공 하지 않 았 으 나 중단 (Interruption) 을 제공 합 니 다. 이것 은 방식 으로 다른 스 레 드 의 현재 작업 을 중단 시 킵 니 다.이러한 협력 식 방법 은 필요 하 다. 우 리 는 특정한 임무, 스 레 드 또는 서비스 가 즉시 중단 되 기 를 원 하지 않 는 다. 왜냐하면 이러한 즉시 중단 은 공 유 된 데이터 구 조 를 일치 하지 않 는 상태 에 처 하 게 할 수 있 기 때문이다.반면 작업 과 서 비 스 를 작성 할 때 협업 방식 을 사용 할 수 있 습 니 다. 멈 춰 야 할 때 현재 실행 중인 작업 을 먼저 지우 고 끝 냅 니 다.이것 은 요청 을 취소 하 는 코드 를 보 내 는 것 보다 작업 자체 의 코드 가 제거 작업 을 어떻게 수행 하 는 지 더 잘 알 기 때문에 더욱 유연성 을 제공 합 니 다.라 이 프 사이클 종료 (End - of - Lifecycle) 의 문 제 는 임무, 서비스, 프로그램의 설계 와 실현 등 과정 을 복잡 하 게 만 들 지만 프로그램 설계 에서 매우 중요 한 요 소 는 무시 되 는 경우 가 많다.행위 가 좋 은 소프트웨어 와 억지로 실행 되 는 소프트웨어 사이 의 가장 큰 차이 점 은 행위 가 좋 은 소프트웨어 가 실패, 폐쇄, 취소 등 과정 을 완벽 하 게 처리 할 수 있다 는 것 이다.어떻게 협력 체 제 를 설계 하여 스 레 드 를 안전하게 중단 시 킬 수 있 습 니까?우 리 는 취소 표 지 를 설정 할 수 있 습 니 다. 작업 스 레 드 가 중단 되 는 곳 에서 이 표 지 를 검사 할 수 있 습 니 다. 이 중단 표지 가 취소 되 었 음 을 확인 하면 작업 스 레 드 는 취소 작업 을 시작 합 니 다.
public class CancelableThread implements Runnable {
    
    //       ,volatile  ,       
    private volatile boolean isCanceled = false;
    
    @Override
    public void run() {
        while (!isCanceled) {//                
            System.out.println("The current thread is doing something...");
            System.out.println(Thread.currentThread().getName() + " cancel flag is " + isCanceled);
        }
        //          true,      ,         
        System.out.println(Thread.currentThread().getName() + "The current thread Has been cancelled");
    }

    private void cancel() {
        isCanceled = true;
    }
}
public class MainTest {
    public static void main(String[] args) throws Exception {
        CancelableThread cancelableThread = new CancelableThread();
        new Thread(cancelableThread).start();
        try {
            Thread.sleep(100);
        } finally {
            //       true,       
      cancelableThread.cancel();
        }
    }
}
  • 인쇄 결과
  • Thread-0 cancel flag is false
    The current thread is doing something...
    Thread-0 cancel flag is false
    The current thread is doing something...
    Thread-0 cancel flag is false
    The current thread is doing something...
    Thread-0 cancel flag is false
    The current thread is doing something...
    Thread-0 cancel flag is true
    Thread-0The current thread Has been cancelled 

    위의 예 를 정리 하면 이 예 는 결함 이 있 습 니 다. run 방법 은 이렇게 쓰 면:
    @Override
    public void run() {
        while(!isCanceled){
            try {
                //            
                Thread.sleep(10000);
            }catch (InterruptedException e){
                //      isInterrupted  ,       
            }
        }
        //        ,    
    }

    만약 에 현재 스 레 드 가 방법 을 실 행 했 을 때 스 레 드 가 걸 렸 습 니 다. 표지 위치 sleep 가 어떻게 변 하 든 순환 을 벗 어 나 지 못 합 니 다. 그러면 우리 가 예상 한 결과 와 일치 하지 않 을 수 있 습 니 다. 따라서 사용자 정의 표지 위 치 를 사용 하여 스 레 드 의 중단 을 제어 하 는 것 을 권장 하지 않 습 니 다. 아래 의 방법 을 사용 해 야 합 니 다.
    Thread 클래스 는 상기 메커니즘 을 실현 하기 위해 세 가지 라인 중단 과 관련 된 방법 을 제공 합 니 다.이 세 가지 방법 은 다음 과 같다.
    public void interrupt() {
      //...        
      interrupt0();           // Just to set the interrupt flag       
      //...        
    }
    public static boolean interrupted() {
        return currentThread().isInterrupted(true);
    }
    public boolean isInterrupted() {
        return isInterrupted(false);
    }
  • isCanceled 방법 은 주로 중단 표지 위 치 를 설정 하 는 데 사용 된다.이 스 레 드 가 호출 interrupt() 방법 이나 wait, join 방법 으로 막 히 면 중단 상태 가 삭 제 됩 니 다 (즉, 스 레 드 가 중단 표지 위 치 를 무시 하지 않 습 니 다). 그리고 sleep 이상 을 받 을 수 있 습 니 다.
  • 정적 InterruptedException 방법 은 현재 스 레 드 가 중단 되 었 는 지 테스트 하 는 데 사 용 됩 니 다. 이 방법 을 사용 하면 스 레 드 의 중단 상 태 를 제거 합 니 다.스 레 드 가 중단 되면 이 방법 을 사용 하여 false 로 되 돌려 줍 니 다.
  • interrupted() 방법 은 현재 스 레 드 가 중단 되 었 는 지 테스트 하지만 스 레 드 의 중단 상 태 를 제거 하지 않 습 니 다.
  • public class InterruptTest {
        static class InnerThread extends Thread{
            @Override
            public void run() {
                while(!isInterrupted()){
                    System.out.println(Thread.currentThread().getName()+" cancle flag is "+isInterrupted());
                    try {
                        Thread.sleep(100);
                    }catch (InterruptedException e){
                        e.printStackTrace();
                        //   InterruptedException,        ,     interrupt();
                        interrupt();
                    }
                }
                System.out.println(Thread.currentThread().getName()+" cancle flag is "+isInterrupted());
            }
        }
    
    
        public static void main(String[] args) {
            InnerThread innerThread = new InnerThread();
            innerThread.start();
            try {
                Thread.sleep(1000);
            }catch (InterruptedException e){
                e.printStackTrace();
            }
            innerThread.interrupt();
    //        InnerThread innerThread2 = new InnerThread();
    //        innerThread2.start();
    //        innerThread2.interrupt();
        }
    }
  • 인쇄 결과
  • Thread-0 cancle flag is false
    Thread-0 cancle flag is false
    Thread-0 cancle flag is false
    Thread-0 cancle flag is false
    Thread-0 cancle flag is false
    Thread-0 cancle flag is false
    Thread-0 cancle flag is false
    Thread-0 cancle flag is false
    Thread-0 cancle flag is false
    Thread-0 cancle flag is false
    java.lang.InterruptedException: sleep interrupted
        at java.lang.Thread.sleep(Native Method)
        at InterruptTest$InnerThread.run(InterruptTest.java:13)
    Thread-0 cancle flag is true

    글 의 출처 (내용 수정):
    https://www.cnblogs.com/perki...
    요약:
  • 일반적인 상황 에서 사용자 정의 인 터 럽 트 플래그 위 치 를 사용 하 는 것 을 권장 하지 않 습 니 다. 원인 은 위 에서 설명 하 였 습 니 다
  • isInterrupted()interrupt 방법 을 결합 하여 사용 하면 절대 다수의 업무 중단
  • 을 해결 할 수 있다.
  • 호출 isInterrupted, wait, sleep 등 차단 또는 연결 방법 을 사용 할 때 중단 이상 을 던 지 는데 왜 이렇게 디자인 합 니까?이것 은 스 레 드 가 특정한 원인 으로 걸 린 후에 후속 업무 가 아직 실행 되 지 않 았 다 면 스 레 드 를 강제 중단 하면 예측 할 수 없 는 결 과 를 초래 할 수 있 습 니 다 (예 를 들 어 파일 이 절반 을 기록 한 것). 스 레 드 를 중단 하려 면 catch 블록 에서 다시 호출 할 수 있 습 니 다 join 방법
  • 정적 interruptinterrupted() 방법 은 모두 호출 된 isInterrupted() 들 어 오 는 private native boolean isInterrupted(boolean ClearInterrupted) 의 값 에 따라 중단 표지 위치
  • 를 제거 할 지 여 부 를 판단 합 니 다.
  • wait, notify, notify All 은 왜 Object 류 에 정의 되 었 습 니까?이것들 은 모두 자물쇠 와 관련 이 있 는데 자 물 쇠 는 대상 에 속한다
  • 좋은 웹페이지 즐겨찾기