start creates a new thread of execution for your thread to execute in, then the thread is scheduled to run and the run method is called by the system when it's ready to run your thread. start will return as soon as the thread has been spawned.
calling run directly is the same as calling any other method, the calling code must wait for the run method to complete and return.
consider the following code:
the output is:
starting s s started s0 s1 s2 s3 s4 running r r0 r1 r2 r3 r4 r ran
I added s.join() to give predictable results, but it's not necessary, try commenting the try/catch block out.
The point is, s executes in another thread, the calling code can continue while the other thread executes (so to speak). when r.run is called, on the other hand, the calling code must wait for the run method to complete before continuing because it is in the same thread of execution.