저번 시간에는 ArrayBlockingQueue에 대해서 잠깐 다룬 적이 있었습니다. 이번에는 Future에 대해서 다뤄 보도록 하겠습니다.

 


 Future<V>에 대한 설명을 보면 위와 같습니다. Future는, 비동기적인 계산에 대한 result를 표현합니다. 그리고, 작업이 완료되어야, 결과를 가져올 수 있습니다. 이 말이 이해가 잘 가지 않네요. 비동기는 나중에 보기로 하고, 작업이 완료 되어야 가져 온다는 말을 이해해 보겠습니다.

 

 

 Future에서 쓸 수 있는 것 중 하나는 get입니다. 이것은, 계산이 완료될 때 까지 기다린 다음에, 그것의 result를 찍는 역할을 합니다. 그런데, 여기서 complete가 나옵니다.

 

 

 Task를 잘 생각해 보면, 진행 중인 상태가 있을 겁니다. 이를 run 상태라 하겠습니다.

 

 

 그리고 그것이 완료되면, complete 상태일 겁니다. 어? 그런데, 이것은 Thread와 다를 바가 없는 듯 합니다.

 


 간단하게 예제 프로그램을 작성해 보겠습니다.

 

 

 먼저, 4번째 줄은, 실행자를 newFixedThreadPool로 설정합니다. 다음에, Future 객체를 생성하는데요. 여기서 중요한 것은 submit입니다.

 

 

 Runnable task를 submit 합니다. 제출한다는 것인데요. 그리고 Future를 리턴합니다. 이것은 Task가 new인 상태임에도, 리턴을 하게 됩니다.

 

 

 submit 안에 execute가 있습니다. 이 부분을 파고 들어가다 보면, ThreadPoolExcutor 클래스의 950번째 줄에 걸리는데요.

 

 

 t는 Thread입니다. 즉, Thread.start()가 요 안에서 호출이 됩니다. 그렇다면, 위 프로그램에서는 submit을 호출하는 과정에서, 새로운 스레드가 생성되었을 겁니다.

 

 

 Task를 등록하는 과정에서, Thread가 생성되고, 예제 코드에서는 새롭게 Thread를 생성하는 것이 없었습니다. 단지, 실행자가 그냥 Task를 실행하게끔 등록을 해 주었을 뿐입니다.

 


 그러면, 이를 토대로, Task의 상태를 간단하게 요렇게 정리할 수 있겠네요. submit, run, complete. 물론, cancel이 있긴 합니다만. 이 부분은 다음에 언급하도록 하겠습니다.

 

 

 10번째 줄에 f1.get()이 있습니다. 이것은, Future가 결과값을 얻을 때 까지 기다립니다. 이 말이 잘 이해가 가질 않는데요. 예제를 살짝 바꾸어서 디버그 해 보겠습니다.

 

 

  아까와 다른 것은 리턴값이 있다는 겁니다. 그리고 11번째 줄과 15번째 줄에 break point를 걸겠습니다.

 

 

 f1이 FutureTask라고 나옵니다. 실제로는, Future를 implements한 클래스입니다. Future 객체라고 하는 게 맞을까요? 그건 잘 모르겠습니다. 아무튼, 결과값을 얻어올 때 까지는 outcome이 null인 상태입니다. 그리고, 이것의 state가 0인 걸로 미뤄 보았을 때, 새로 생성된 상태임을 알 수 있습니다.

 

 

 그런데, 15번째 줄에 도달하니, outcome이 5가 나왔습니다. 이 결과값은 작업이 완료되었을 때에만 얻을 수 있음을 알 수 있습니다. 지연 초기화를 했다고 보시면, 조금 더 정확할 듯 합니다.