반응형

스프링 비동기와 자바8의 CompletableFuture Spring Async and Java’s 8 CompletableFuture


아래는 '비동기' 유저찾기 메소드의 예제의 구현이다. (전체 소스는 여기)

1@Async
2public Future<User> findUser(String user) throws InterruptedException {
3  System.out.println("Looking up " + user);
4  User results = restTemplate.getForObject("https://api.github.com/users/" + user, User.class);
5  // Artificial delay of 1s for demonstration purposes
6  Thread.sleep(1000L);
7  return new AsyncResult<User>(results);
8}

나는 왜 여전히 'Future'가 이 예제에 있는지 궁금했다. 나는 원작자가 이미 자바8의 새로운 CompletableFuture가 있는 걸 알고 있지만, 아마 자바 6나 7과의 이전 버전 호환성을 고려해서 남겨두었다고 생각했다.

여기있는 매우 정갈한 예제를 보면 이러한 의문을 가진건 나 혼자만은 아닌것 같다. 이 글의 답글 중 하나에서, 당신은 스프링 API 버전 4.2 에 포함되어 있는 힌트 - 이미 지원하고 있는 Future와 AsyncResult에서 CompletableFuture를 사용이 호환가능하다는 를 볼 수 있을 것이다. 나는 '누군가가 이 예제를 돌리면 그는 아마 현재의 구현에 머무를 것이므로 직접 적용해보거나 문서화 하지않는 것은 부끄러운 일이다'라는 생각이 들었다. 표준화된 방법을 사용하지않을 이유가 없다.

그래서 나는 Future를 지우고 CompletableFuture로 바꾸는 작은 수정을 하기로 했다. 또한 Future.isDone() 구문을 주석처리하고  CompletableFuture.allof() 메소드로 대체할 것이다.

또한 호출자 코드를 업데이트하면서 3개의 future 들을 동기화하도록 'service' 메소드의 리턴타입을 바꿨다. 일단 allof() 모두 완료되면 우리는 결과를 출력할 수 있다.

01package hello;
02 
03import java.util.concurrent.CompletableFuture;
04import java.util.concurrent.Future;
05 
06import org.springframework.scheduling.annotation.Async;
07import org.springframework.scheduling.annotation.AsyncResult;
08import org.springframework.stereotype.Service;
09import org.springframework.web.client.RestTemplate;
10 
11@Service
12public class GitHubLookupService {
13 
14    RestTemplate restTemplate = new RestTemplate();
15 
16    @Async
17    public CompletableFuture findUser(String user) throws InterruptedException {
18        System.out.println("Looking up " + user);
19        User results = restTemplate.getForObject("https://api.github.com/users/" + user, User.class);
20        // Artificial delay of 1s for demonstration purposes
21        Thread.sleep(1000L);
22        return CompletableFuture.completedFuture(results);
23    }
24 
25}

이 수정된 예제는 여기서 받을 수 있다. 나는 Tomasz Nirkewicz의 블로그에서 CompletableFuture의 풍부한 메소드 리스트를 매우 실용적이고 멋있게 설명한 이 글이 글을 찾았다. 또한 매우 완벽한 프리젠테이션도 여기서 받을 수 있다.


01@Override
02    public void run(String... args) throws Exception {
03        // Start the clock
04        long start = System.currentTimeMillis();
05 
06        // Kick of multiple, asynchronous lookups
07        CompletableFuture page1 = gitHubLookupService.findUser("PivotalSoftware");
08        CompletableFuture page2 = gitHubLookupService.findUser("CloudFoundry");
09        CompletableFuture page3 = gitHubLookupService.findUser("Spring-Projects");
10 
11        // Wait until they are all done
12        //while (!(page1.isDone() && page2.isDone() && page3.isDone())) {
13          //  Thread.sleep(10); //10-millisecond pause between each check
14        //}
15 
16        //wait until all they are completed.
17        CompletableFuture.allOf(page1,page2,page3).join();
18        //I could join as well if interested.
19 
20        // Print results, including elapsed time
21        System.out.println("Elapsed time: " + (System.currentTimeMillis() - start) +" ms");
22        System.out.println(page1.get());
23        System.out.println(page2.get());
24        System.out.println(page3.get());
25    }



반응형

+ Recent posts