The second case is "working" because you sleep the main thread long enough (5 seconds). Working is between quotes because it isn't really working, just finishing. I'm assuming here the code should output Hello World!
in order to be considered "working properly".
Try the same code with this sleep time at the end of the main thread in both cases:
Thread.sleep(100);
1. The first one would behave in the same way, as the get operation blocks the main thread. In fact, for the first case, you don't even need the last sleep time.
Output: Hello World!
2. The second case won't output Hello
, as no one told the main thread: "hey, wait for this to finish". That's what get()
does: block the caller in order to wait for the task to finish. Without it, and setting a low sleep time at the end, the runnable is called, but couldn't finish its job before the main thread stops.
Output: World!
That's also the reason why in the first case Hello World!
(first the runnable's output, and then main's one- meaning the main thread was blocked until get()
returned) is written, while the second one shows subtle signs of dyslexia: World Hello!
But it's not dyslexic, it just executes what it is told to. In the second case, this happens:
1. The runnable is called.
2. Main thread continues its process, printing ("World!)
3. Sleep
times are set: 1 second on the runnable / 5 seconds on main. (runnable's sleep could also be executed during the 2nd step, but I put it here in order to clarify the behaviour)
4. The runnable task prints ("Hello") after 1 second and the CompletableFuture is finished.
5. 5 Seconds passed, main thread stops.
So your runnable could print Hello
because it was able to execute the command in between those 5 seconds timeout.
World! . . . . . .(1)Hello. . . . . . . . . . .(5)[END]
If you decrease the last 5 seconds timeout, for example, to 0.5 seconds, you get
World!. . (0.5)[END]