2014-04-20 3 views
10
CompletableFuture.supplyAsync(
() -> { 
    transporter.write(req); 
    //here take the value from a blocking queue,will throw a interruptedException 
    return responseQueue.take(); 
}, executorService); 

interruptedException을 처리하는 일반적인 방법은 다시 인터럽트하거나 interruptedException을 throw하는 것이지만 둘 다 작동하지 않습니다. 누구나 아이디어가 있으십니까?JDK8 CompletableFuture.supplyAsync interruptedException을 처리하는 방법

+0

"*하지만 둘 다 작동하지 않습니다." "=> 왜? – assylias

+0

모두 컴파일러 오류가 있습니다. 직접 throw 예외가 발생하면 컴파일러는 처리되지 않은 예외를 표시하고 catch하고 Thead.current.interrupt를 호출하면 컴파일러에서 T 유형을 반환해야합니다. – GrapeBaBa

+0

예. 돌아 오거나 던지십시오. 널 (null)을 리턴하기로 결정한 경우, 다음과 같습니다.'try {return queue.take(); } catch (InterruptedException e) {Thread.currentThread(). interrupt(); null를 돌려 준다. }' – assylias

답변

10

나는 이와 같은 코드를 변경합니다.

CompletableFuture<Rep> result = new CompletableFuture<>(); 
    CompletableFuture.runAsync(() -> { 

     transporter.write(req); 
     try { 
      Rep rep = responseQueue.take(); 
      result.complete(rep); 
     } catch (InterruptedException e) { 
      result.completeExceptionally(e); 
      Thread.currentThread().interrupt(); 
     } catch (Exception e) { 
      result.completeExceptionally(e); 
     } 

    }, executorService); 
    return result; 
+0

당신이 한 일은 제 것과 같습니다. 아아,'CompletableFuture result'는 "결과 또는 예외"패러다임을 따르는 ANY 클래스로 대체 될 수 있습니다. 예를 들어'get','complete'와'completeExceptionally' 메소드를'ResultWrapper'에 추가하고'ResultWrapper rep = new ResultWrapper();'를 사용할 수 있습니다. 'CompletableFuture'를 사용하여이 람다 함수의 한계를 만나고 다시'CompletableFuture'를 사용하여 해결 한 우연의 일치가 여러분이 사용한 메소드를 사용합니다. – mostruash

+1

예,하지만 completablefuture에는 이미 계산 결과에 대한 추상화가 있으므로 동일한 유형에 대해 새 유형을 생성하고 싶지는 않습니다. – GrapeBaBa

+0

다른 사람들과 함께 일하는 경우 코드 독자가 혼란 스러울 수 있습니다. 그렇지 않다면, 그것은 당신을 위해 잘 작동합니다. – mostruash

3

람다 함수는 예외를 throw하는 것을 지원하지 않으므로 Java 개발자는 새로운 패러다임이 필요하다고 생각합니다. 한 가지 생각하면 다음과 같습니다 :

람다 함수는이 래퍼의 인스턴스를 반환 할 수 있습니다. (편집 : 귀하의 사례)

CompletableFuture<ResultWrapper<String, InterruptedException>> aFuture = ...; 
... 
aFuture.supplyAsync(
() -> { 
    try { 
     transporter.write(req); 
    } catch(InterruptedException e) { 
     ResultWrapper<String, InterruptedException> r = new ResultWrapper<>(); 
     r.exception = e; 
     r.result = null; 
     return r; 
    } 
    ... 
}, executorService); 
+0

해결책으로 보입니다. – GrapeBaBa

+0

도움이된다고 생각되면 답변으로 표시하십시오. – mostruash

+0

예외를 반환 값으로 변환하는 대신 확인되지 않은 예외로 래핑하고 필요한 경우 외부의 확인 된 예외로 다시 변환해야합니다. 예외 전체를 예외로 유지하십시오. 리턴 값은 오류가없는 조건을 위해 예약되어 있습니다. – Gili

2

나는 같은 질문으로 실행하지만, 더 여기 의견과 참고 도서에서 읽은 후 나는 당신이 이들 중 하나를 수행 할 수 있다고 생각 :

1 (I은 결국 무엇 일) :

CompletableFuture.runAsync(() -> { 
    transporter.write(req); 
    try { 
     Rep rep = responseQueue.take(); 
     result.complete(rep); 
    } catch (Exception e) { 
     throw new CompletionException(e); 
    } 
}, executorService); 
return result; 

또는 2 :

CompletableFuture<Rep> result = new CompletableFuture<>(); 
new Thread(()-> { 
    transporter.write(req); 
    try { 
     Rep rep = responseQueue.take(); 
     result.complete(rep); 
    } catch (Exception e) { 
     retsult.completeExceptionally(e); 
    } 
}).start(); 

나는 2 일이 executorService를 사용하지 않습니다 알고 있지만, CompletableFuture를 사용하는 전체 요점이 기능 스타일로 CompletionStage API를 활용하고 있다고 생각합니다.

+0

두 번째 해결 방법을 개선 할 수 있습니다. 자세한 설명은 http://stackoverflow.com/a/28961083/868941을 참조하십시오. – rmuller

관련 문제