<Java> Future
by BFine가. Future
a. 무엇인가
- 비동기 작업에 대한 결과라는 의미를 담고 있는 인터페이스로 비동기 작업을 기다리고 가져오고 , 완료 or 취소 되었는지 확인하거나 하는 기능을 한다.
b. 예제 만들기
public static void main(String[] args) throws InterruptedException, ExecutionException {
ExecutorService executorService = Executors.newSingleThreadExecutor();
Callable<String> callable = ()-> {
TimeUnit.MILLISECONDS.sleep(500);
System.out.println("실행 " + Thread.currentThread());
return "world";
};
Future<String> submit = executorService.submit(callable);
for (int i = 0; i < 6; i++) {
TimeUnit.MILLISECONDS.sleep(100);
if(submit.isDone()){
System.out.println("끝! " + Thread.currentThread());
break;
}else {
System.out.println("처리중.. " + Thread.currentThread());
}
}
System.out.println(submit.get());
executorService.shutdownNow();
}
- .isDone 을 활용해서 작업이 끝났는지 여부를 확인해보도록 만들어보았다. 비동기 작업이 callback 되어지기 전까지는 처리중으로 보여진다.
=> ExecuterSerivce 에 비동기 작업을 .submit 했을때 비동기 작업이 실행된다.
- 위에서는 .get 이전에 완료되어 바로 출력이 되었지만 처리중이 였을경우 .get 에서는 블로킹이 발생한다.
- 그러면 이 Future 장점은 무엇인지 확인해보자
public static void main(String[] args) throws InterruptedException, ExecutionException {
ExecutorService executorService = Executors.newSingleThreadExecutor();
Callable<String> callable = ()-> {
System.out.println("큰일 하는 중.. " + Thread.currentThread());
TimeUnit.MILLISECONDS.sleep(500);
System.out.println("큰일 조금만 기다려줘.. " + Thread.currentThread());
TimeUnit.MILLISECONDS.sleep(500);
System.out.println("큰일 끝." + Thread.currentThread());
return "world";
};
Future<String> submit = executorService.submit(callable);
TimeUnit.MILLISECONDS.sleep(300);
System.out.println("작은일 처리1 "+Thread.currentThread());
TimeUnit.MILLISECONDS.sleep(200);
System.out.println("작은일 처리2 "+Thread.currentThread());
TimeUnit.MILLISECONDS.sleep(600);
System.out.println("작은일 처리3 "+Thread.currentThread());
String world = submit.get();
System.out.println("hello " + world);
executorService.shutdownNow();
}
- 여기서 가장 중요한 부분은 비동기 작업의 결과를 Future를 통해 전달 받아 아래의 로직을 구현할 수 있는 부분 이다.
c. 논블록킹
- 어떤 작업이 진행되고 계산된 결과가 return 될때까지 기다리지 않고 바로 약속을 return 받는 것을 논블로킹이라고 한다.
=> 예를들어 카페에서 주문을 하고 커피가 나올때까지 기다리는게 아니라 진동벨을 받는 것과 같다.
- 위의 디버깅 해보면 .submit 시점에 바로 완료되지 않는 FutureTask를 return 받는 것을 볼 수 있다.
d. FutureTask
- FutureTask는 Runnable과 Future 인터페이스를 구현한 구현체 클래스이다.
- 클래스를 살펴보면 6단계의 상태를 가지는 것을 할 수 있고 취소, Exception, 인터럽트 발생 시 에 대한 상태값도 가지고 있는 것을 볼 수 있다.
- .run 을 살펴보면 비동기 처리와 동일하게 ExecuterService에서 생성한 새로운 Thread에서 처리되고 있는 것을 볼 수있다.
e. 블로킹
- .get 이 호출되면 블로킹이 발생한다고 위에 말했는데 어떻게 블로킹 처리를 하는지 궁금해졌다. 확인해보면
- state가 아직 NEW, COMPLETING 인 경우 .awitDone 으로 들어오고 내부를 살펴보면 무한 반복문을 볼 수 있다.
- 그리고 COMPLETING 인 경우에는 Thread.yield를, NEW 인 경우에는 LockSupport.park 을 이용해서 블로킹 처리를 하고 있는 것을 알 수 있었다.
=> .yield는 우선순위가 같은 다른 Thread 에게 기회를 주기위해 현재 Thread를 대기상태로 만든다.
- LockSupport.park 했으니 LockSupport.unpark 하는 작업이 필요하다. 이부분은 .run 에서 비동기 작업이 끝났을 경우 .set 를 호출하며
이안에 있는 .finishCompletion 에서 처리하고 있다.
'공부 > Java' 카테고리의 다른 글
<Java> 그룹으로 묶어서 정렬하기 (2) | 2023.01.23 |
---|---|
<Java> CompletableFuture (0) | 2022.08.02 |
<Java> Thread 와 비동기 (0) | 2022.01.20 |
ForkJoinPool의 Thread Size 고정이 안되는 경우 (3) | 2021.02.26 |
<모던자바인액션> Stream API, JMH, Parallel Stream (0) | 2021.02.21 |
블로그의 정보
57개월 BackEnd
BFine