Explore how Java's `CompletableFuture` operates asynchronously, even without blocking calls, and learn its internal workings and practical examples.
---
This video is based on the question https://stackoverflow.com/q/65605550/ asked by the user 'SangHoon Lee' ( https://stackoverflow.com/u/11524087/ ) and on the answer https://stackoverflow.com/a/65606195/ provided by the user 'Eugene' ( https://stackoverflow.com/u/1059372/ ) at 'Stack Overflow' website. Thanks to these great users and Stackexchange community for their contributions.
Visit these links for original content and any more details, such as alternate solutions, latest updates/developments on topic, comments, revision history etc. For example, the original title of the Question was: Why does this CompletableFuture work even when I don't call get() or join()?
Also, Content (except music) licensed under CC BY-SA https://meta.stackexchange.com/help/l...
The original Question post is licensed under the 'CC BY-SA 4.0' ( https://creativecommons.org/licenses/... ) license, and the original Answer post is licensed under the 'CC BY-SA 4.0' ( https://creativecommons.org/licenses/... ) license.
If anything seems off to you, please feel free to write me at vlogize [AT] gmail [DOT] com.
---
Understanding how CompletableFuture works even without calling get() or join()
In the world of Java programming, particularly when working with multithreading, CompletableFuture has become a popular choice for handling asynchronous tasks. One common question developers encounter is: Why does a CompletableFuture work even when I don't explicitly call get() or join()?
In this guide, we'll explore this intricate question, breakdown the functionality and internal processes of CompletableFuture, and clarify why your code may still function correctly, even without blocking calls.
The Basics of CompletableFuture
CompletableFuture is part of the java.util.concurrent package and is designed for asynchronous programming. The main idea is that these futures allow you to write non-blocking code that can handle tasks that may take time to complete, such as network calls or heavy computations.
Key Characteristics:
Asynchronous Execution: CompletableFuture does not block the calling thread. It allows tasks to run in the background while the main thread continues processing other operations.
Completions: Completes when a certain condition is met, either successfully or exceptionally, and can be manually completed or canceled.
Calls to get() and join()
To understand the significance of not calling get() or join(), let’s first discuss what happens when you use these methods.
Both get() and join() are blocking calls.
They wait for the CompletableFuture to complete before proceeding further in the code.
Example:
[[See Video to Reveal this Text or Code Snippet]]
Output:
[[See Video to Reveal this Text or Code Snippet]]
In this case, "Hello" is printed first because we waited for the asynchronous task to complete.
Case of Not Calling get() or join()
In another scenario, consider what happens when neither get() nor join() is called:
[[See Video to Reveal this Text or Code Snippet]]
Output:
[[See Video to Reveal this Text or Code Snippet]]
Explanation of Output
Immediate Scheduling: When runAsync is called, the task is immediately scheduled for execution. This means it starts running in the background, independent of the main thread.
No Blocking: Since we didn’t call get() or join(), the main thread doesn't wait for the background task to finish before it executes the following System.out.println("World!");.
As a result, the main thread continues running and outputs "World!" before "Hello".
Understanding Completion States
The beauty of CompletableFuture lies in its non-blocking behavior. By the time you reach an optional point where you may invoke get() or join(), the asynchronous task might already have completed, hence there’s no need to block.
What Happens Internally?
The computation happens asynchronously, and the completion of tasks fills in the callback pipeline you might have set up. Here’s a handy representation of a processing example:
[[See Video to Reveal this Text or Code Snippet]]
The key takeaway is that, by the time join() is executed, all previous stages might have already been completed without requiring you to call get() or join() at every step.
Directly Completing a CompletableFuture
Moreover, you can manually complete a CompletableFuture without waiting for tasks to finish:
[[See Video to Reveal this Text or Code Snippet]]
Output:
[[See Video to Reveal this Text or Code Snippet]]
Final Observations
Even when the asynchronous task has already begun, manually completing it leads to an output of "b" rather than the expected result of "a".
Conclusion
In summary, CompletableFuture is designed for seamless asynchronous programming. By understanding its behavior, you can effectively manage and control the execution of concu
Информация по комментариям в разработке