TL;DR ⚡
Abstract
- Thread states: NEW → RUNNABLE → (RUNNING) → BLOCKED / WAITING / TIMED_WAITING → TERMINATED.
join()= “wait for that thread to finish before I continue.” It is NOT fork/join, and it does not return/combine results.
The 6 thread states (java.lang.Thread.State)
- NEW — created (
new Thread()), not started. - RUNNABLE —
start()called; eligible to run (running or ready-to-run — the OS scheduler decides). - BLOCKED — waiting to acquire a
synchronizedlock another thread holds. - WAITING — waiting indefinitely for another thread (
wait(),join()with no timeout). - TIMED_WAITING — waiting for a set time (
sleep(ms),join(ms),wait(ms)). - TERMINATED —
run()finished (or threw).
Note: there’s no separate “RUNNING” enum — actually-executing is part of RUNNABLE.
What is join()?
threadA.join() called from the main thread means: “main pauses here until threadA finishes.” It’s how you wait for a worker to complete before using its side effects.
Thread worker = new Thread(task);
worker.start();
worker.join(); // main WAITS here until worker is done
System.out.println("worker finished, continue");Common confusions (yours!)
- Is join() part of fork/join? No. Fork/Join is a separate framework (
ForkJoinPool, work-stealing, for divide-and-conquer parallelism).Thread.join()is just “wait for this thread.” Different things that share the word “join.” - Does join() combine results from two threads? No.
join()returnsvoid— it only waits. To get a result back you useFuture/CompletableFuture(see CompletableFuture). To combine two async results, that’sCompletableFuture.thenCombine.join()only synchronizes timing, not data.
Mental model
join() = “I’ll wait at the door until you come out.” It does not carry anything out of the room — that’s what Futures are for.
Test Yourself
Name the thread states.::NEW, RUNNABLE, BLOCKED, WAITING, TIMED_WAITING, TERMINATED.
What does join() do?::Makes the calling thread wait until the target thread finishes. Returns void — no result.
Is join() the same as Fork/Join?::No — Fork/Join is a separate divide-and-conquer framework (ForkJoinPool). join() just waits for a thread.
How do you get a RESULT from a thread (not just wait)?::Use Future / CompletableFuture; join() only synchronizes timing, it returns nothing.