7 취소 및 닫 기

12101 단어
콘 셉 트
  • 중단 (Interruption) 은 하나의 스 레 드 가 다른 스 레 드 의 현재 작업 을 중지 할 수 있 는 협력 체제 이다.
  • 중단 은 취소 작업 에 만 적합 하 며 취소 이외 의 다른 작업 에 사용 하면 적합 하지 않 습 니 다.중단 은 취 소 를 실현 하 는 가장 합 리 적 인 방식 이다.

  • 중단 은 필요 하 다
  • 저 희 는 특정한 임무, 스 레 드 또는 서비스 가 즉시 중단 되 기 를 원 하지 않 습 니 다. 그러면 공 유 된 데이터 구 조 를 일치 하지 않 는 상태 에 처 하 게 할 수 있 기 때 문 입 니 다.이러한 협력 체 제 를 중단 시 키 려 면 작업 을 중단 해 야 할 때 작업 은 먼저 현재 실행 중인 작업 을 제거 한 다음 에 끝 납 니 다. 작업 자체 의 코드 가 요청 한 코드 보다 제거 작업 을 어떻게 수행 하 는 지 더 잘 알 기 때 문 입 니 다.

  • 행위 의 좋 고 나 쁨 의 프로그램의 차이
  • 행위 가 좋 은 절 차 는 실패, 폐쇄 와 취소 등 상황 을 완벽 하 게 처리 할 수 있다.

  • 작업 개념 취소
  • 외부 코드 는 특정한 작업 이 정상적으로 완성 되 기 전에 '완성' 상태 로 설정 할 수 있다
  • .
    작업 취소 원인
  • 사용자 가 취소 요청 (예: 사용자 가 취소 버튼 을 클릭)
  • 시간 제한 이 있 는 조작 (예 를 들 어 퀘 스 트 수행 시간 초과 시 퀘 스 트 취소)
  • 응용 프로그램 이벤트 (예 를 들 어 하나의 작업 의 완료 이벤트 로 인해 다른 작업 이 취소 되 었 습 니 다)
  • 오류 (예 를 들 어 하나의 작업 에 오류 가 발생 하여 다른 작업 이 취소 되 었 습 니 다)
  • 닫 기 (예 를 들 어 프로그램 실행 종료, 긴 작업 취소)
  • 작업 취소 정책
  • 방법: 외부 코드 가 작업 취 소 를 요청 하 는 방법
  • When: 외부 코드 가 취소 되 었 는 지 확인 하 는 작업
  • What: 작업 이 취소 되 었 을 때 어떤 작업 을 수행 해 야 합 니까?
  • 스 레 드 인 터 럽 트 정책
  • 인 터 럽 트 전략 규정 스 레 드 는 특정한 인 터 럽 트 요 구 를 어떻게 설명 하 는 지
  • 가장 합 리 적 인 인 터 럽 트 전략 은 특정한 스 레 드 급 이나 서비스 급 취소 작업 입 니 다.
  • 빨리 탈퇴 하거나 InterrupteException 이상 던 지기
  • 필요 할 때 청소 하기 (라인 이 중 단 된 후에 청소 할 수 있 습 니 다. 예 를 들 어 shutdown 방법 에서 청소 할 수 있 습 니 다)
  • 한 소유자 에 게 이 스 레 드 가 종료 되 었 음 을 알 립 니 다 (중 단 된 스 레 드 의 상태 가 중단 되 었 음 을 표시 합 니 다)
  • 다른 자주 사용 하 는 인 터 럽 트 정책: 서 비 스 를 중단 하고 서 비 스 를 다시 시작 합 니 다. 이러한 비 표준 인 터 럽 트 정책 을 포함 하 는 스 레 드 나 스 레 드 풀 은 이러한 정책 을 아 는 작업 에 만 적 용 됩 니 다.

  • 주: 작업 에 취소 정책 이 포함 되 어야 하 는 것 처럼 스 레 드 에 도 인 터 럽 트 정책 이 포함 되 어야 합 니 다.
    Thread 인 터 럽 트 관련 작업
  • interrut: 대상 스 레 드 를 중단 하 는 데 사용
  • isInterrupted: 대상 스 레 드 가 중단 되 었 는 지 확인 하 는 데 사용
  • Thread. interrupted: 현재 스 레 드 의 인 터 럽 트 상 태 를 제거 하고 이전의 인 터 럽 트 상 태 를 되 돌려 줍 니 다. 이것 은 인 터 럽 트 상 태 를 제거 하 는 유일한 방법 입 니 다
  • 주 1: 목표 스 레 드 가 끝 났 으 면 isInterrupted 는 처음부터 끝까지 false 로 돌아 갑 니 다!
    주 2: interrupt 를 호출 하 는 것 은 목표 스 레 드 가 실행 중인 작업 을 즉시 중단 하 는 것 이 아니 라 중단 요청 정 보 를 전달 하 는 것 입 니 다!
    인 터 럽 트 차단 라 이브 러 리 지원
  • Thread.sleep
  • Thread.join
  • Object.wait

  • 주: 인 터 럽 트 에 응답 하 는 동작 은 인 터 럽 트 상 태 를 지우 고 Interrupted Exception 을 던 지 는 것 입 니 다.즉, Interrupted Exception 을 받 았 을 때 중단 상 태 는 false!
    요청 수신 자 중단
  • 작업 과 스 레 드 는 모두 요청 을 중단 한 수신 자 입 니 다. 중단 요청 이 도 착 했 을 때 '작업 취소' 와 '작업 자 스 레 드 닫 기'
  • 가 필요 합 니 다.
  • 작업 은 자신 이 가지 고 있 는 스 레 드 에서 실행 되 지 않 습 니 다 (작업 은 작업 일 뿐 스 레 드 가 아 닙 니 다). 작업 은 비 스 레 드 소유자 입 니 다. 중단 요청 을 처리 할 때 중단 상 태 를 조 심 스 럽 게 저장 해 야 스 레 드 소유자 가 중단 에 응답 할 수 있 습 니 다. 다른 후속 '비 소유자' 도 응답 할 수 있 습 니 다.

  • 작업 응답 중단 두 가지 방식
  • 이상 전달 중단 예외
  • 인 터 럽 트 상태 회복 (Thread. interrupt 방법 호출)
  • 주 1: 작업 은 이 작업 을 수행 하 는 스 레 드 의 인 터 럽 트 전략 에 대해 어떠한 가설 도 해 서 는 안 됩 니 다. 이 작업 이 서비스 에서 실행 되 고 이 서비스 에 특정한 인 터 럽 트 전략 을 포함 하지 않 는 한!
    주 2: 스 레 드 인 터 럽 트 정책 을 실현 한 코드 만 인 터 럽 트 요청 을 차단 할 수 있 습 니 다. 일반적인 작업 과 라 이브 러 리 코드 에서 인 터 럽 트 요청 을 차단 해 서 는 안 됩 니 다!
    스 레 드 를 어떻게 중단 합 니까?
  • 스 레 드 는 소유자 가 중단 할 수 있 습 니 다. 소유 자 는 스 레 드 의 중단 정책 정 보 를 적당 한 취소 체제 에 밀봉 할 수 있 습 니 다. 닫 으 면 (shutdown) 방법 입 니 다.

  • 인 터 럽 트 에 대한 작업 응답
  • 차단 방법 을 중단 하 는 작업 을 취소 하고 호출 하 는 것 을 지원 합 니 다. 작업 을 빨리 취소 하고 중단 상 태 를 회복 해 야 합 니 다
  • 취 소 는 지원 되 지 않 지만 순환 중 중단 차단 방법 을 호출 하 는 작업 은 로 컬 에 중단 상 태 를 저장 하고 작업 이 돌아 오기 전에 중단 상 태 를 회복 해 야 합 니 다. 캡 처 중단 시 회복 하 는 것 이 아니 라 로 컬 에 중단 상 태 를 저장 해 야 합 니 다
  • 차단 방법 을 중단 하 는 작업 을 호출 하지 않 고 순환 중 현재 스 레 드 의 중단 상 태 를 돌아 가면 서 중단 에 응답 합 니 다
  • 자바 인 터 럽 트 메커니즘 의 장점
  • 자바 중단 은 비 선점 식 중단 으로 중단 요청 의 처 리 를 지연 시 키 고 개발 자 는 유연 한 단말기 전략 을 지정 하여 응용 프로그램 이 응답 성과 건설 성 사이 에서 합 리 적 인 균형 을 이 룰 수 있 도록 한다.

  • 표준 취소 작업 예제
    package cn.weicm.cancel;
    
    import java.util.concurrent.Executors;
    import java.util.concurrent.ScheduledExecutorService;
    import java.util.concurrent.ScheduledFuture;
    import java.util.concurrent.TimeUnit;
    
    /**
     * Time:	2018/8/3 13:52
    * Auth: weicm
    *
    * Desp:
    *
    * :
    *
      *
    • , timedRun
    • *
    *
    * :
    *
      *
    • , , timedRun
    • *
    • , timedRun , ,
    • *
    */ public class TimedRun1 { private static final ScheduledExecutorService ses = Executors.newScheduledThreadPool(1); public static void main(String[] args) { try { timedRun(() -> { System.out.println("Task start ..."); try { TimeUnit.SECONDS.sleep(10); } catch (InterruptedException e) { System.out.println("Task is canceled!"); // , InterruptedException, Thread.interrupt() , return; } System.out.println("Task end ..."); }, 1, TimeUnit.SECONDS); } finally { ses.shutdown(); } } /** * Time: 2018/8/3 14:20
    * Auth: weicm
    *
    * Desp: ,
    * * @param task * @param timeout * @param unit */ static void timedRun(Runnable task, long timeout, TimeUnit unit) { // , Thread currentThread = Thread.currentThread(); // ScheduledFuture> future = ses.schedule(() -> { currentThread.interrupt(); }, timeout, unit); task.run(); // , , , future.cancel(true); } }
    package cn.weicm.cancel;
    
    import java.util.concurrent.Executors;
    import java.util.concurrent.ScheduledExecutorService;
    import java.util.concurrent.ScheduledFuture;
    import java.util.concurrent.TimeUnit;
    
    /**
     * Time:	2018/8/3 15:36
    * Auth: weicm
    *
    * Desp:
    * * :
    *
      *
    • TimedRun1
    • *
    * * :
    *
      *
    • join , join
    • *
    */ public class TimedRun2 { private static final ScheduledExecutorService ses = Executors.newScheduledThreadPool(1); public static void main(String[] args) throws Throwable { try { timedRun(() -> { System.out.println("Task start ..."); try { TimeUnit.SECONDS.sleep(10); } catch (InterruptedException e) { System.out.println("Task is canceled!"); // , InterruptedException, Thread.interrupt() , return; } System.out.println("Task end ..."); }, 1, TimeUnit.SECONDS); } finally { ses.shutdown(); } } /** * Time: 2018/8/3 14:20
    * Auth: weicm
    *
    * Desp: ,
    * * @param task * @param timeout * @param unit */ static void timedRun(Runnable task, long timeout, TimeUnit unit) throws Throwable { /** * Time: 2018/8/3 14:42
    * Auth: weicm
    *
    * Desp:
    */ class ThrowableTask implements Runnable { private volatile Throwable e; @Override public void run() { try { task.run(); } catch (Throwable e) { // : , , this.e = e; } } /** * Time: 2018/8/3 15:33
    * Auth: weicm
    *
    * Desp:
    * * @throws Throwable */ public void rethrow() throws Throwable { if (null != e) throw e; } } // ThrowableTask t = new ThrowableTask(); Thread taskThread = new Thread(t); taskThread.start(); // ScheduledFuture> future = ses.schedule(() -> { taskThread.interrupt(); }, timeout, unit); taskThread.join(unit.toMillis(timeout)); // , , , future.cancel(true); // t.rethrow(); } }
    package cn.weicm.cancel;
    
    import java.util.concurrent.*;
    
    /**
     * Time:	2018/8/3 16:38
    * Auth: weicm
    *
    * Desp: Future
    * * :
    *
      *
    • TimedRun2 ,
    • *
    * * Futrue.cancel:
    *
      *
    • : true false, , ,
    • *
    • : true ; false ,
    • *
    • : true false,cancel ,
    • *
    */ public class TimedRun3 { private static final ExecutorService es = Executors.newSingleThreadExecutor(); public static void main(String[] args) throws Exception{ try { timedRun(() -> { System.out.println("Task start ..."); try { TimeUnit.SECONDS.sleep(10); } catch (InterruptedException e) { System.out.println("Task is canceled!"); // , InterruptedException, Thread.interrupt() , return; } System.out.println("Task end ..."); }, 1, TimeUnit.SECONDS); } finally { es.shutdown(); } } /** * Time: 2018/8/3 14:20
    * Auth: weicm
    *
    * Desp: ,
    * * @param task * @param timeout * @param unit */ static void timedRun(Runnable task, long timeout, TimeUnit unit) throws Exception { Future> future = es.submit(task); try { future.get(timeout, unit); } catch (InterruptedException e) { // , Thread.currentThread().interrupt(); } catch (ExecutionException e) { // , throw e; } catch (TimeoutException e) { // , , } finally { // , ; , , , // ! future.cancel(true); } } }

    끊 을 수 없 는 차단
  • Thread. interrupt 은 중단 할 수 없 는 작업 을 수행 하 는 데 차단 되 는 스 레 드 에 대해 스 레 드 의 중단 상태 만 설정 할 수 있 습 니 다. 그 밖 에 다른 역할 이 없습니다.그러나 이 스 레 드 를 중단 하 는 것 과 유사 한 수단 을 사용 할 수 있 지만 스 레 드 가 막 힌 원인 을 알 아야 합 니 다.

  • 자주 중단 할 수 없 는 차단 작업
  • 자바. io 패키지 의 동기 화 Socket I / O: InputStream. read 와 OutputStream. write 는 소켓 (Socket. close) 을 닫 아 Socket Exception 을 던 질 수 있 습 니 다.
  • 자바. io 패키지 의 동기 화 I / O: 그 중에서 Interruptible Channel 에서 기다 리 고 있 는 스 레 드 를 끊 을 때 Closed ByInterrupteException 을 던 지고 링크 를 닫 습 니 다. 이 링크 에서 막 힌 다른 스 레 드 도 Closed ByInterrupteException 을 던 집 니 다.Interruptible Channel 을 닫 으 면 링크 작업 에서 막 힌 모든 스 레 드 가 Asynchronous Close Exception 을 던 집 니 다.
  • Selector 의 비동기 I / O: 한 스 레 드 가 Selector. select 방법 을 호출 할 때 막 히 면 close 나 wakeup 방법 을 호출 하면 스 레 드 를 Closed Selector Exception 으로 던 지고 미리 되 돌려 줍 니 다.
  • 특정한 자 물 쇠 를 가 져 옵 니 다. 만약 에 하나의 스 레 드 가 내 장 된 자 물 쇠 를 기다 리 는 것 으로 막 히 면 중단 에 응답 할 수 없습니다. 스 레 드 는 반드시 자 물 쇠 를 얻 을 것 이 라 고 생각 하기 때문에 중단 요청 을 무시 합 니 다.그러나 Lock 클래스 에 서 는 lockInterruptibley 방법 을 제공 합 니 다. 이 방법 은 자 물 쇠 를 기다 리 는 동시에 중단 에 응답 할 수 있 습 니 다.
  • 좋은 웹페이지 즐겨찾기