Future는 미래의 결과를 받을 수 있는 객체입니다
Future<Integer> future = service.submit(new TaskCallable());
submit()의 호출로 TaskCallable 인스턴스를 전달합니다
이때, Future를 반환합니다
잘 생각해보면 TaskCallable가 즉시 실행되는 것이 아니기에 결과를 즉시 반환받는것은 불가능합니다
스레드 풀의 스레드가 미래의 어떤 시점에 이 코들르 대신 실행해야 합니다
TaskCallable.call()은 호출 스레드가 실행하는 것이 아니고, 스레드 풀의 다른 스레드가 실행하기 때문에
언제 실행되어서 결과를 반환받을지 모릅니다
따라서 결과를 즉시 받는 것은 불가능하고, 이를 위해 Future라는 객체를 대신 제공합니다
즉, Future는 작업의 미래 결과를 담고 있다고 할 수 있습니다
submit()을 호출해서 ExecutorService에 task1을 전달한다고 가정해보겠습니다
ExecutorService는 전달한 task1의 미래 결과를 알 수 있는 Future 객체를 생성합니다
Future는 인터페이스고 실제 구현체는 FutureTask입니다
생성한 Future 객체 안에서 task1 인스턴스를 보관하고, 내부적으로 작업완료 여부와
작업의 결과값을 가집니다
그리고 블로킹 큐에는 task1을 감싸고 있는 Future가 대신 담깁니다
작업을 전달할 때 생성된 Future는 즉시 반환됩니다
따라서 요청 스레드는 대기하지 않고 자유롭게 본인의 다음 코드를 호출할 수 있습니다
이것은 Thread.start()를 호출한 것과 비슷합니다
Thread.start()를 호출하면 스레드의 작업 코드가 별도의 스레드에서 실행됩니다
이렇게 되면 요청 스레드는 대기하지 않고, 즉시 다음 코드를 호출할 수 있습니다
아직 스레드1이 task1의 작업을 처리중이고 완료되지 않은 상태라고 가정해보겠습니다
요청 스레드는 Future 인스턴스의 참조를 가지고 있고, 원할 때 Future.get()을 호출해서
작업의 미래 결과를 받을 수 있습니다
task1의 작업이 완료되면 Future의 상태도 완료로 변경됩니다
이때 future.get()을 요청 스레드가 호출하면 Future가 완료상태가 될때까지 대기합니다
이때 요청 스레드의 상태는 RUNNABLE에서 WAITING으로 변합니다
Future가 완료상태라면 Future에 결과도 포함되어 있습니다
이 경우는 요청 스레드가 대기하지 않고 값을 즉시 반환받을 수 있습니다
Future가 완료상태가 아니면 task1이 아직 수행되지 않았거나 수행중이라는 뜻으로
요청 스레드가 결과를 받기 위해 대기해야합니다
요청 스레드가 락을 얻을 때처럼 결과를 얻기 위해 대기하는데
이렇게 스레드가 어떤 결과를 얻기 위해 대기하는 것을 블로킹이라고 합니다
Thread.join(), Future.get()과 같은 메소드는 스레드가 작업을 바로 수행하지 않고,
다른 작업이 완료될때까지 기다리는 메소드입니다
이러한 메소드를 호출하면 호출한 스레드는 지정된 작업이 완료될때까지 블로킹 되어 다른 작업을 수행할 수 없습니다
WAITING 상태로 future.get()을 호출하고 대기중입니다
task1의 작업을 완료하고 Future에 반환 결과를 담고 상태를 완료로 변경합니다
그리고 요청 스레드를 깨우고 요청 스레드는 WAITING에서 RUNNABLE 상태로 변합니다
이후 요청 스레드에서는 Future를 반환받습니다. Future에는 task의 결과가 담겨져 있습니다
스레드1은 스레드 풀로 반환되고, RUNNABLE에서 WAITING 상태로 변화합니다
Future는 작업의 미래 결과를 받을 수 있는 객체입니다
submit()을 호출하면 future는 즉시 반환되며, 요청 스레드가 블로킹되지 않고, 필요한 작업을 할 수 있습니다
작업의 결과는 Future.get()을 호출하면 됩니다
Future가 완료상태라면 즉시 반환받고 아니라면 블로킹 상태로 대기해야 합니다
그런데 Future에 대해 한가지 의문이 들 수 있습니다
ExecutorService를 설계할 때부터 Future를 반환하는게 아니라 결과를 직접 받도록 한다면
더 단순하고 좋지 않을까? 라는 의문이 들 수도 있습니다
이렇게 하면 submit()을 호출할 때 작업의 결과가 언제 나오는지 알 수 없고,
요청 스레드가 결과를 받을 때까지 대기해야합니다
근데 이것도 결곽 Future도 마찬가지입니다 Future만 즉시 반환 받을 뿐이고,
작업의 결과를 얻으려면 Future.get()을 결국 호출해야합니다
그리고 이시점에서 작업의 결과를 받을 때까지 대기해야합니다
그렇다면 Future가 왜 필요할까요? 이것에 대해 알기 위해 활용 에제를 더 살펴보겠습니다