fromFuture() vs fromCallable() 생성 연산자에 대해
안녕하세요,
fromFuture() 생성 연산자가 저한테 와 닫지않아 따로 구글링을 해봤는데요,
https://beomseok95.tistory.com/11?category=1029204
해당 링크 글 마지막에 보시면
'fromCallable()과 다른점은 결과 값을 받을 때까지 블로킹한다'라고 설명되어있습니다
그래서 이 각각의 연산자들은 서로 비슷한 연산자인데 역할이 다른 것인지 궁금하고, 각 연산자들의 활용되는 예시가 궁금합니다
* fromFuture() 연산자
* fromCallable() 연산자
回答 2
0
안녕하세요? 점심 시간이라서 잠깐 짬내서 답변 드립니다.
시간이 많지가 않아서 간단한 예제로 말씀을 드릴게요.
일단 말씀하신 두개 연산자의 차이점을 설명 드리기 전에 먼저 알아야 될 것은 Callable과 Future인데요.
우리가 Plain Java(이하, Java)에서 쓰레드를 별도로 생성하여 비동기 작업을 실행 시키기 위해서 일반적으로 Runnable 인터페이스를 사용하는데요.
Runnable과 Callable의 차이점은 작업이 끝난 후에 결과 값을 return 하느야 그렇지 않느냐라는건 잘 알고 계실꺼라고 생각합니다.
그런데 Callable의 경우, 비동기적으로 작업이 수행되기 때문에 Callable의 call() 메서드를 호출하는 대상 클래스(일반적으로 main 쓰레드)에서 call() 메서드를 호출한다고해서 return 값을 바로 반환 받을 수 가 없습니다. 왜냐면 예를 들어서 main 쓰레드에서 call() 을 호출하고 별도의 쓰레드에서 작업을 수행하는 동안 main 쓰레드는 이미 종료되어 버릴지도 모르니까요.
그렇기 때문에 Callable 인터페이스를 통해 생성된 별도의 작업 쓰레드가 작업이 끝날때까지 Callable 인터페이스에게 작업을 요청한 대상 쓰레드(일반적으로 main 쓰레드)는 작업 쓰레드의 작업이 끝날때까지 기다렸다가 결과 값을 return 받아야 하는데요. Callable을 통해 생성된 작업 쓰레드의 작업이 끝날때 까지 기다려주는 역할을 하는 것이 바로 Future 인터페이스입니다.
아래에서 Callable과 Future에 대한 예제를 살펴보겠습니다.
==== PlainJavaCallableExample01 ====
public class PlainJavaCallableExample01 {
public static void main(String[] args)
throws ExecutionException, InterruptedException {
Callable<Integer> callable = new SumCallable();
FutureTask futureTask = new FutureTask(callable);
Thread thread = new Thread(futureTask);
thread.start();
System.out.println(futureTask.get());
}
public static class SumCallable implements Callable<Integer> {
@Override
public Integer call() throws Exception {
// 시간이 오래 걸리는 작업
Thread.sleep(5000L);
int sum = 0;
for (int i = 1; i <= 10; i++) {
sum += i;
}
return sum;
}
}
}
Callable 을 통해 생성된 작업 쓰레드에서 1부터 10까지 더해서 총합을 return 하는 간단한 예제인데요.
시간이 오래 걸리는 작업이라고 가정하고 5초 정도 딜레이 시간을 주었습니다.
위에서 빨간색으로 되어 있는 FutureTask라는 놈이 보이시죠? FutureTask는 Future 인터페이스의 구현체인데 작업 쓰레드가 작업이 끝날때까지 기다려주는 역할을 합니다. 작업 쓰레드에서 작업이 끝날때까지 기다렸다가 futureTask.get()을 통해서 결과 값을 return 받는 것을 보실 수가 있겠습니다.
예제를 하나 더 보겠습니다.
==== PlainJavaCallableExample02 ====
public class PlainJavaCallableExample02 {
public static void main(String[] args)
throws ExecutionException, InterruptedException {
Callable<Integer> callable = new SumCallable();
ExecutorService executorService =
Executors.newSingleThreadExecutor();
Future<Integer> future = executorService.submit(callable);
System.out.println(future.get());
executorService.shutdown();
}
public static class SumCallable implements Callable<Integer> {
@Override
public Integer call() throws Exception {
// 시간이 오래 걸리는 작업
Thread.sleep(5000L);
int sum = 0;
for (int i = 1; i <= 10; i++) {
sum += i;
}
return sum;
}
}
}
Callable이나 Runnable 은 ExecutorService 라는 인터페이스와 함께 사용되는 경우가 일반적인데요. ExecutorService 는 쓰레드를 관리해주는 관리자의 역할을 한다고 보시면 되겠습니다.
아무튼 위 코드에서 빨간색으로 된 라인을 보시면 Callable을 통해 생성된 작업 쓰레드를 ExecutorService에 submit 한 후, 실행이 되면 작업이 끝난 후에 Future 를 반환합니다.
이 Future를 통해서 작업 쓰레드의 작업이 끝날때까지 기다렸다가 결과 값을 return 받게 되는것입니다.
자, 그럼 RxJava에서 fromFuture()와 fromCallable()은 언제 사용할 수 있고, 차이점은 무엇일까요?
질문자님께서 말씀하신대로 두 연산자의 역할은 거의 같다라고 보시는게 맞습니다. 다만 fromFuture()는 파라미터로 Future를 입력받고, fromCallable()은 파라미터로 Callable 인터페이스 객체를 입력 받는다는 차이점 밖에 없습니다. 차이점이 너무 싱겁다고 생각드시죠?
그러면 같은 기능을 하는데 왜 굳이 두가지 연산자가 필요하냐는 의문이 드실 수 가 있는데요.
아마도 RxJava가 아닌 Plain Java 코드로 구성되어 있는 레거시 애플리케이션의 코드에서 RxJava의 연산자를 사용해야 될 때가 있을텐데, 같은 프로세스를 코드로 구현하더라도 누구는 Callable을 return하는 API를 만들어 놓았을 수 있고, 다른 누구는 Future를 return하는 API 를 만들어 놓았을 수도 있기때문이지 않을까 싶네요. 즉, 기존의 다양한 레거시 코드에서 RxJava를 사용할 수 있도록 배려한 부분이 있다라는 생각이 듭니다.
단적인 예가 fromIterable()과 fromArray() 연산자라는 생각이 들어요. 배열이나 List나 둘 다 서로 변환이 가능하기 때문에 두 연산자 중에 하나만 있으면 되는건데도 둘 다 만들어 놓은건 연산자를 사용하는 사람들에게 선택의 폭을 넓혀주기 위한거라는 생각이 듭니다.
답변이 충분히 되셨나 모르겠네요.
그럼 저는 그만 오후 업무를 봐야겠습니다.
좋은 하루 되세요!
Single과 관련해 여쭤보고 싶은 부분이 있습니다!
0
264
2
cold/hot publisher 예제 코드와 관련해 질문 드립니다.
0
363
1
CompletableObserver 클래스의 람다식 표현관련
0
297
1
1강에 예시로 보여주신 ToDoSample 코드에 관해 질문 드립니다!
0
356
1
데이터 결합 연산자 / merge 관련 질문
0
445
1
DROP 배압 전략에 관한 궁금증
0
300
2
map에서의 TimeUtil.sleep에 관한 궁금점
0
216
1
강의 내용을 정리해서 개인 블로그에 올려도 될까요?
0
562
2
TimeUtil.sleep 관련 질문
0
286
1
배압 전략 중에서 DROP 전략과 관련해서 질문 있습니다.
0
335
1
Error 발생 시에도 계속 처리 방법
0
689
2
선언형 프로그래밍과 명령형 프로그래밍
1
784
2
첫번째 강의 부터 이번강의까지 수강하면서 궁금한점 질문드립니다.
0
325
1
안녕하세요. 질문이 있습니다.
1
354
1
logger 가 없는데 util 폴더도 같이 갖다놔야 하나요?
0
327
1
amb 연산자
0
233
1
질문 드립니다.
0
219
1
concatEager( ) 연산자에 관하여
0
318
1
Reactive Streams의 구성요소들과 RxJava의 구성요소들의 관계?
1
397
2
ObservableSequenceEqualExample.java 예제의 delay( ) 연산자 질문있습니다
0
309
3
defer( ), fromFuture( )도 just( )처럼 여러 인자 값을 받을 수 있는지 궁금합니다.
0
264
3
flatMapSingle() 메소드에 대하여
0
620
6
함수형 인터페이스 Comparator에 대해
0
397
2
Publisher와 Subscriber 간의 프로세스 흐름에 대한 질문
1
340
3

