2010-07-17 10 views
11

mayInterruptIfRunning 매개 변수에 대해 false 매개 변수를 Future.cancel()으로 전달하려는 경우 어떤 상황이 발생합니까? 당신이 false 전달하고 작업이 취소되지만 스레드가 중단 결과 (또는 ExecutionException) 액세스 할 수 없을 것 하지 경우 작업이 여전히 표시되어 있으므로 (즉 isCancelled() 반환 true 취소로Future.cancel (false)의 사용 사례?

내가 제대로 이해한다면 및 get()CancellationException을 던진다)

다른 가능한 상황입니다.

  • Runnable 또는 Callable 구현 D 히어로 인터럽트를 확인하고이 과정을 중단 할 경우에도 완료 될 때까지 실행되지는 cancel()라고하기 전에 작업이 이미 완료
  • (여기 인터럽트가 차이가 없습니다)
  • 작업이 필요 (다시 인터럽트는 차이가 없습니다) 종료하기 전에 정리를 수행하십시오. 잘 작성된 구현에서는이 경우 을 사용합니다.
  • 작업을 즉시 종료 할 수 없으며 인터럽트의 영향을받는 작업을 계속 수행해야합니다 (예 : I/O 차단 (이 경우에는 cancel을 호출하지 않아야합니다.)

언제/왜 작업을 중단하지 않고 취소하겠습니까?

답변

6

작업 실행을 중단하는 것이 두려운 경우 상황이 좋지 않은 상태로 남겨두고 취소 된 것으로 표시하여 Future 사용자가 알 수 있도록해야합니다 (예 : 요청한 통계를 알 수 있어야 함). 시간에 공연하지 않았다.)

인터럽트를 올바르게 처리하는 쓰레드 된 코드를 작성하는 것은 전혀 쉬운 일이 아니므로,이를 피하는 것이 더 좋을 수도 있습니다.

일부 정보는 here, here이며 물론 위대한 책 Concurrent Programming in Java (원래 java.util.concurrent을 작성한 사람이 있음)에서 찾을 수 있습니다.

+0

첫 번째 진술은 적절하지 않습니다. 작업이 실행 중이거나 취소 (false)보다 완료되면 취소로 표시되지 않습니다. – Ryan

7

tl; dr; Future.cancel(false)은 아직 시작되지 않은 작업을 시작하지 않는 데 유용합니다.

동시성 및 취소와 관련하여 이해해야 할 두 가지 중요한 사항이 있습니다.

첫 번째는 Java 취소가 순수하게 협조적이라는 것입니다. Java는 블로킹 메소드가 InterruptedExcetions를 발생시키고 스레드에 플래그를 설정함으로써 취소 요청을 알립니다. 작업 구현은 취소 요청을 알리고 자체를 취소하는 역할을합니다. Brian Goetz는 그의 게시물 Dealing with InterruptedException에서 중단에 대해 설명합니다. 모든 작업 구현이 인터럽트를 올바르게 처리하는 것은 아닙니다.

두 번째로 지적해야 할 점은 Future 개체는 미래에 실행될 작업의 결과에 대한 자리 표시 자입니다. 많은 스레드가 실행되고 있지 않다면 즉시 작업이 시작되지만 모든 스레드가 이미 사용되고 작업이 대기해야 할 수도 있습니다. 실제로 해당 작업이 실제로 실행되기 시작한 것은 아니라는 Future 개체에 대한 참조가 있기 때문입니다. 그 종류의 예약.

당신은 미래의 목적을 가지고 있지만 작업의 상태는 다음 중 하나 일 수 있습니다

  1. 대기. 예를 들어 프로세서 시간을 기다리는 다른 작업 큐에있을 수 있습니다.
  2. 실행 중입니다.
  3. 완료되었습니다.

작업이 "대기 중"인 경우 Future.cancel(true)Future.cancel(false)은 취소 된 것으로 미래를 표시합니다. 태스크는 실행할 태스크 큐에 남아 있지만 실행 프 N 그 %이 타스크에 도달하면 취소 된 플래그를 알아 차리고이를 건너]니다.

작업이 Future.cancel(true)Future.cancel(false)보다 "완료된"세 번째 상태 인 경우 false를 반환하고 아무 것도하지 않습니다. 이미 완료 되었기 때문에 의미가 있습니다. 실행 취소 할 방법이 없습니다.

mayInterruptIfRunning 플래그는 작업이 두 번째 "실행 중"상태 인 경우에만 중요합니다.

작업이 실행 중이고 mayInterruptIfRunning이 false이면 실행 프로그램은 아무 작업도 수행하지 않고 작업을 완료하도록 허용합니다.

작업이 실행 중이고 mayInterruptIfRunning이 true이면 실행 프로그램이 작업을 인터럽트합니다. 그러나 협업 취소에 대한 약간의 기억 - 취소 작업을 처리하기 위해 중단 작업을 구현해야합니다.

  1. 미래 중단을 처리하기 위해 구현 된 것으로 알려진 장기 실행 작업을 나타냅니다

    는 요약 : 때

    Future.cancel(true) 적합합니다.

Future.cancel(false)은 올바른 것 :

  1. 이 작업 구현이

    을 중단하고 처리 할 수 ​​없습니다.
  2. 작업 구현이 취소를 지원하는지 여부는 알 수 없습니다.
  3. 이미 시작된 작업이 완료되기를 기다리고 있습니다.
1

나는 당신에게 흥미로운 유스 케이스를 가지고있다 : 나는 한 세트의 예약 된 작업을 실행하는 스레드를 가지고있다. 작업 중 하나는 자체 또는 다른 작업에 의해 다시 스케줄 될 수 있습니다.

이렇게하려면 대기열에있는 기존 복사본에 Future.cancel(false)을 사용하고 새 시간으로 작업을 예약하십시오.

이 코드가 예약 된 작업 자체에서 호출 된 경우 취소 작업은 아무 작업도 수행하지 않으며 이후에 작업이 다시 실행되도록 예약됩니다. 코드가 다른 컨텍스트에서 호출되면 다가오는 작업은 아직 실행되지 않았으므로 취소되고 새 시간에 예약 된 작업으로 바뀝니다.