Does Scala Future[T] block internally? What happens inside Scala Future?
Asked Answered
T

1

6
val future = Future {
   println("hello")
   Thread.sleep(2000)
}

future.onComplete(_ => println("done"))

The code in the future above blocks.

My question is: since Future uses an ExecutionContext. Does it mean that some thread in this thread pool will be blocked by this future while executing the code inside it?

What thread exactly will call the callback? Another thread from the thread pool? How will it find out that the code executed inside this future is finished?

Tampa answered 27/3, 2017 at 20:10 Comment(1)
You could check the ID of the thread inside the future to see what threads it's on.Decrescent
P
4

Assuming you're calling code that blocks in a Future:

since Future uses ExecutionContext. Does it mean, that some thread in this thread pool will be blocked by this future while executing the code inside it?

Essentially, yes. If you're calling blocking code, something has to be blocked. An ExecutionContext is more general than a thread pool, though. It can be thread pool, but it can also be just something that manages calls in some other way. Still, something will be blocked, more often than not it will be a thread. scala.concurrent.ExecutionContext.Implicits.global is a ForkJoinPool, for example.

What thread exactly will call the callback?

That is mostly up to the ExecutionContext to decide. You can print Thread.currentThread in your callback code, but there is no reason (other than maybe debugging) why you really need to know this information. Your code certainly shouldn't need to know. Typically this means the next available thread in the pool, which could be the same thread that executed the body of the Future, or a different one. It appears that the same thread that executes the original Future will dispatch the callbacks, but that only schedules them for execution.

How will it find out, that the code execution inside this future is finished?

Calling onComplete will either execute immediately if the underlying Promise of the Future is in the completed state, or a CallbackRunnable will be added to a list of listeners to be executed when the promise is completed. DefaultPromise#tryComplete will call the listeners immediately after the computation has executed. See this excerpt of the current code.

Pencel answered 27/3, 2017 at 20:52 Comment(6)
Thank you for an excellent answer. I have one more question though. Since futures are based on threads and they block internally some thread, they're not event-driven. There is no thing like even-loop being executed event by event. Why do we say, that futures are "event-driven"? (I found this in "Learning Concurrent Programming in Scala" by Aleksandar Prokopec)Tampa
@Tampa Since you can block the event loop in Node.js, does that mean that Node.js is not event-driven. (i.e. who came up with the claim that something isn't event-driven is there is possibility of blocking?)Jezabel
@ViktorKlang Sorry, this seems to be a newbie question, but I've been reading a lot on this recently and I didn't find the final answer. Maybe I should rephrase my question: Scala Futures are based on thread pools (more or less by default), whereas Node.js is based on event loop executing events, so what makes Futures in Scala event-driven? Is it the fact, that when it gets completed, the attached callback(s) get executed?Tampa
@Tampa What do you think executes the Node.js event loop?Jezabel
@Tampa Futures are event driven because their callbacks/transformations are submitted for execution based on completion events of the associated Promises.Jezabel
@ViktorKlang And that's the answer to my question. Thanks a lot √Tampa

© 2022 - 2024 — McMap. All rights reserved.