2012-01-17 2 views
12

미래를 중단하지 않고 중단 할 수있는 방법이 있습니까?동시성 - 미래를 중단하지 않고 중단하기

java doc API:

부울 이 작업의 실행을 취소 할 수 (부울 mayInterruptIfRunning)

시도를 취소 할 수 있습니다. 작업이 이미 완료되었거나 이미 취소되었거나 다른 이유로 인해 취소 될 수없는 경우이 시도는 실패합니다. 성공한 경우 취소 작업이 호출 될 때이 작업에 이 시작되지 않았 으면이 작업이 실행되지 않아야합니다. 작업이 이미 시작된 경우 mayInterruptIfRunning 매개 변수 은이 작업을 실행하는 스레드가 작업을 중지하기 위해 중단 된 이어야하는지 여부를 결정합니다.

인터럽트를 캡처하려면 인터럽트 된 예외를 제대로 catch하거나 Runnable/Callable 메서드 내에서 isInterrupted() 메서드를 확인해야합니다.

그러나 모든 스레드가 집행자 서비스 풀에 있기 때문에 미래 인터페이스

를 사용하여 실행중인 미래를 중단 할 수있는 방법이 없다가, 아무도 thread.interrupt을 할 수 없다(). 그런 이유로 Future가 취소되거나 Thread Pool이 종료 될 때만 인터럽트가 발생한다고 가정 되었습니까?

미래 인터페이스에 인터럽트 방법이없는 이유를 이해하려고합니다. 도움이 될 것입니다.

+1

나는이 점이 무엇이 될지 궁금해. 흥미롭지 만 그리 이상하지 않은 질문이다. –

+5

몇 가지 문제가 있습니다. 1.) 인터럽트는 위험이며, 작업이 언제 중단 될 수 있는지 언제 알지 못합니다. 2) 미래가 어떤 스레드에도 묶여 있지 않습니다. Interrupt Future의 스레드는 다른 Futures를 깨뜨릴 수 있습니다. 3) 취소 메커니즘을 사용하면 인종 및 교착 상태와 관련된 가장 일반적인 함정 중 하나를 피할 수 있습니다. 4.) 코드가 무작위로 중지되지 않을 것이라고 높은 확신을 얻습니다 상태. – Rekin

+0

"Future는 비동기 계산의 결과를 나타냅니다."- 비동기 엔티티를 인터럽트하는 것은 위험합니다. 호출하는 스레드가 계속 작동 할 수 있고 비동기 엔티티에서 응답을 기다리고 있기 때문입니다. –

답변

7

이유는 미래의 추상화와 스레드에서의 구체적인 실행이 다르기 때문입니다. 미래가 단일 스레드 또는 다중 스레드에 묶여 있는지 말할 수 없습니다. 미래는 새로운 스레드를 시작하고 새로운 선물을 시작할 수 있습니다.

클라이언트 코드와 미래의 집행자 간의 상호 작용으로 이러한 추상화를 고려하십시오. 개념적으로 취소 할 작업 이었기 때문에 "내가 요청한이 작업 취소"라고 말하는 것이 합리적입니다. 나는 그것에 바쁘다, 또는 아직 그것을 시작하지 않았을 수도 있습니다, 또는 그것은 끝날 수도 있지만 괜찮아요, 나는 당신이 원한다면 그것을 취소합니다. 그래서 우리는 취소 방법을 가지고 있습니다.

반면에, "당신의 작업을 방해하라"는 말은별로 의미가 없습니다. 동작 결과 (Future)와 실행 모델 (Executor) 사이의 분리 때문에 클라이언트는 작업을 수행하기 위해 수행되는 동작을 알지 못합니다. 그렇다면 클라이언트는 인터럽트가 언제 적절하고 필요하며 심지어 지원되는지를 어떻게 예상 할 수 있습니까?

+1

http://docs.oracle.com/javase/tutorial/essential/concurrency/interrupt.html - 인터럽트는 스레드가 수행중인 작업을 중지하고 다른 작업을해야한다는 표시입니다. 스레드가 인터럽트에 어떻게 반응하는지는 프로그래머가 결정하지만 스레드가 종료되는 경우는 매우 일반적입니다. 미래의 경우 인터럽트는 종료를 의미합니다. 인터럽트로 수행 할 수있는 것이 무엇이든, 미래는 조건을 기다리는 것과 같이 스스로 해결해야한다는 것에 동의합니다. 하지만 미래를 방해하는 것은 의미가 없다는 것에는 동의하지 않습니다. 복잡성은 가치가 없을 수도 있습니다. – AKSG

0

아무리 빨리 시간 초과를 사용할 수 있으므로 기다리는 시간을 방해 할 수 있습니다.

get(long timeout, TimeUnit unit) 
+0

호출자 스레드에서 실제로 대기하지만, Future에서 결과를 얻기 위해 로직을 실행하는 스레드가 없습니다. 부분적 결과를 얻기 위해 흥미로운 [코딩 과제 : 부분 결과 의미론] (http://beust.com/weblog/2014/05/24/coding-challenge-partial-results-semantics/)이 스레드 인터럽트에 관련되어 있습니다. . –

0

이렇게하는 데 유용한 유스 케이스가 있습니다.

미래 API의 문제점은 실행이 중지되었음을 감지하기 위해 기능을 제공하지 않는다는 것입니다. isCancelled()isDone()은 Callable 실행이 계속 실행 되더라도 행복하게 반환됩니다.

그럼이 단계에서 미래 API의 추상화 수준과 관련이 없습니다. 그러나 작업 종료를 식별 할 수 없습니다. 다르게 말하면, 취소 요청과 완료 취소 조치을 구분할 수 없습니다.

Waiting for a cancelled future to actually finish과 같이 CountdownLatch을 사용하는 것이 하나의 해결 방법입니다. 그러면 대기중인 발신자에게 작업이 실제로 완료되었음을 알리고 중지 신호 만 보내지 않습니다.

관련 문제