인프런 커뮤니티 질문&답변

덩더러러쿨님의 프로필 이미지

작성한 질문수

Kevin의 알기 쉬운 RxJava 1부

유틸리티 연산자

ObservableSequenceEqualExample.java 예제의 delay( ) 연산자 질문있습니다

해결된 질문

작성

·

194

0

안녕하세요,

해당 예제에서의 delay( ) 연산자를 첫 번째 유형(delay(Long delay, TimeUnit unit))으로 바꿔보았는데, 콘솔에 수행 결과 출력없이 종료됩니다.

public class ObservableSequenceEqualExample {
public static void main(String[] args) {
Observable<CarMaker> observable1 =
Observable.fromArray(SampleData.carMakers)
.subscribeOn(Schedulers.computation())
.delay(300L, TimeUnit.MILLISECONDS)
.doOnNext(data -> Logger.log(LogType.DO_ON_NEXT, "# observable1 : " + data));

Observable<CarMaker> observable2 =
Observable.fromArray(SampleData.carMakers)
.delay(100L, TimeUnit.MILLISECONDS)
.doOnNext(data -> Logger.log(LogType.DO_ON_NEXT, "# observable2 : " + data));

Observable.sequenceEqual(observable1, observable2)
.subscribe(data -> Logger.log(LogType.ON_NEXT, data));
}
}

Schedules.computation을 설정해서 그런가 싶어 주석 처리해보아도 결과는 동일했습니다.

어째서 두 유형의 delay( )이 결과 값이 다른지 모르겠습니다


* 추가 내용 (자문자답 아님!)

왜 이러한 차이점이 있는지 확인해본 바로는
첫 번째 유형의 delay는 아래와 같이 스케줄러를 통해 computation 스레드로 지정하는 것을 확인했습니다. 이 때문에 observable1, observable2가 각 스레드 computation로 실행되기 때문에 Thread.sleep( )을 주지 않는 이상 콘솔에 출력이 안되는 것 같습니다.

- Observable.java

@CheckReturnValue
@SchedulerSupport(SchedulerSupport.COMPUTATION)
public final Observable<T> delay(long delay, TimeUnit unit) {
return delay(delay, unit, Schedulers.computation(), false);
}

반면 두 번째 유형의 delay 코드는 첫 번째 유형과 달리 실행할 스레드를 지정하는 코드가 없고 flatMap을 통해 데이터를 1개 씩 리턴하기 때문에 sequenceEqual( ) 연산자가 각각의 데이터를 비교할 수 있는 것이 아닐까 추측해봅니다...

@CheckReturnValue
@SchedulerSupport(SchedulerSupport.NONE)
public final <U> Observable<T> delay(final Function<? super T, ? extends ObservableSource<U>> itemDelay) {
ObjectHelper.requireNonNull(itemDelay, "itemDelay is null");
return flatMap(ObservableInternalHelper.itemDelay(itemDelay));
}

혹시 제가 추측한 내용 중에 틀린 부분이 있는지 확인부탁드립니다ㅜ

답변 3

1

Kevin님의 프로필 이미지
Kevin
지식공유자

안녕하세요. 오늘도 열심히 학습 중이시군요. ^^

질문하신 부분에 대해서 답변을 드려보자면,

"첫 번째 유형의 delay는 아래와 같이 스케줄러를 통해 computation 스레드로 지정하는 것을 확인했습니다. 이 때문에 observable1, observable2가 각 스레드 computation로 실행되기 때문에 Thread.sleep( )을 주지 않는 이상 콘솔에 출력이 안되는 것 같습니다."

--> 네, 맞습니다. delay 연산자도 interval 연산자와 마찬가지로 computation 쓰레드가 default 라서 그렇습니다.

"반면 두 번째 유형의 delay 코드는 첫 번째 유형과 달리 실행할 스레드를 지정하는 코드가 없고 flatMap을 통해 데이터를 1개 씩 리턴하기 때문에 sequenceEqual( ) 연산자가 각각의 데이터를 비교할 수 있는 것이 아닐까 추측해봅니다..."

--> 첫번째 유형의 delay 연산자를 사용해도 Thread.sleep( )을 주게 되면 sequenceEqual( ) 연산자가 정상적으로 동작합니다. 첫번째 delay 연산자 유형은 생산자 쪽에서 첫번째 데이터를 통지하기 전에 한번만 딜레이를 시키는 것이고 두번째 delay 연산자 유형은 생산자 쪽에서 데이터가 하나씩 통지될때 마다 delay를 시킨다는 것인데 어떤 유형의 dealy 연산자를 사용하더라도 sequenceEqual 연산자는 정상 동작을 합니다. 

0

다른 수강생들이 참고하면 좋을 것 같아 댓글 추가합니다

예제 ObservableDelayExample02.java에 로그를 출력시켜 확인해보았는데요, 첫 번째 유형의 delay( ) 연산자만 computation 스레드에서 실행되는 것 같습니다

- Code & Result

public class ObservableDelayExample02 {
public static void main(String[] args) {
Observable.just(1,3,5,7)
.delay(item -> {
TimeUtil.sleep(1000L);
Logger.log(LogType.DO_ON_NEXT, item);
return Observable.just(item); // 새로운 Observable의 통지 시점에, 원본 데이터를 통지한다.
}).subscribe(data -> Logger.log(LogType.ON_NEXT, data));
}
}
doOnNext() | main | 20:20:38.076 | 1
onNext() | main | 20:20:38.148 | 1
doOnNext() | main | 20:20:39.148 | 3
onNext() | main | 20:20:39.148 | 3
doOnNext() | main | 20:20:40.159 | 5
onNext() | main | 20:20:40.159 | 5
doOnNext() | main | 20:20:41.160 | 7
onNext() | main | 20:20:41.160 | 7

이름은 같은 연산자인데 왜 이렇게 내부동작이 다른걸까요? 사람 헷갈리게ㅜㅜ

0

 이제야 이해했습니다 답변 감사합니다!

이건 다른 질문인데요, Reactor에 대해서 관련 강의가 나오기 전에 미리 공부를 해보려고 합니다.

혹시 추천할만한 서적이나 관련 자료가 있을까요??

Kevin님의 프로필 이미지
Kevin
지식공유자

가장 확실한건 reactor 공식 사이트의 레퍼런스 문서이구요.

한국어로 된 도서에서 Reactor만 다루는 도서는 현재까지 없을 듯 싶어요.

해외 도서는 한 권이 있는데, 아래 링크 참조하시면 될것 같네요.

https://www.packtpub.com/product/hands-on-reactive-programming-in-spring-5/9781787284951

감사합니다!