Here's question # 54 from Marcus Green's mock exam #1: Mock Java Certification Exam Output is: One One Two Two I do not understand how the thread functionality can be implemented without calling the start() method first. It makes sense to use the run method - for we have one implemented - but what about using sleep(), yield(), etc. before even starting the thread? Thanks, Saket
Ooohhhh I like this one. Good one Marcus! He never does start any threads, so in fact the *only* threads that are running are those started by the JVM. As far as *you* are concerned, there is only one thread and thus one call stack -- main. So here's what happens: 1) He makes an instance of Pmcraven, passing a name "one" to its constructor. At this point, it's just a plain old object on the heap like every other object. No special "threadness". This is how all threads start their life. 2) He invokes the run() method on that object. Doesn't matter if that method were the foo() method or the go() method or anything else. There is nothing special about run(), as a method name, unless you really DO start a thread, in which case, the thread then knows that the first method to call is run(). 3) So, you're always free to call run() on a Thread instance yourself. But that means you get a plain old Thread object's run() method, but you don't get any *threadness*. In other words, you don't get a shiny new call stack. Here's the key... 4) The run() method in this example is called from the *main* thread, rather than from the new thread that would have been created if he had called start() on the Thread instance. 5) So what about yield() and sleep()? Well, remember what those methods do. They are static methods of class Thread. But what do they do? They sleep() or yield() THE CURRENTLY RUNNING THREAD. In other words, the *main* thread. 6) To put it into a timeline... 1) instance one is created and put on the heap 2) instance one has its run() method invoked. 3) the run() method begins, and starts a loop. 4) the run() method encounters a sleep() call. This puts the main thread to sleep! Because main is the currently running thread, main goes to sleep. 5) There is no chance for the other Thread instance to be created, because the call stack is frozen at that sleep() call. So the scheduler selects another thread to run, like the garbage collector. 6) the sleep timer expires, and the *main* thread returns to runnable. The scheduler picks it again, and then it hits a yield() call, which probably has NO affect at all since main is almost certainly the highest priority thread. 7) finally, the System.out println prints the name. 8) the loop isn't finished, so it starts again and does the whole thing I just described, ending with printing "one" again. 9) the run() method completes, and is popped off the main call stack. 10) Now we move to the next line of code in the main() method, which instantiates the second Thread instance and off we go... Just remember: - There is only ONE user-generated thread / call stack: main - It is perfectly OK to call a Thread object's run() method, but this does not mean you will get an actual *thread of execution*.
- It is fine to call sleep() and yield() with a Thread instance, because they are inherited methods from Thread (static, but that's OK). cheers, Kathy p.s. you can expect something vaguel similar on the real exam... something to see if you understand that calling a Thread object's run() does not make a new thread/call stack.
Co-Author of <a href="http://www.amazon.com/exec/obidos/ASIN/0596007124/ref=jranch-20" target="_blank" rel="nofollow">"Head First Design Patterns"</a><br /> <br />Just a Jini girl living in a J2EE world.
Great explanation Kathy. One thing though, I'm confused as to why the proccesing ends up in the catch "block" at all ?? Surely no InterruptedException occurs calling the Thread.sleep()?? Just a mainframe-boy in a OO world
Originally posted by Johannes de Jong: Great explanation Kathy. One thing though, I'm confused as to why the proccesing ends up in the catch "block" at all ?? Surely no InterruptedException occurs calling the Thread.sleep()?? ]
It don't enter the catch block, Johannes. If it did it would have output the thread's name. It will enter the catch block only if something interrupt()s the main thread, and nothing does. But the thread's name does get printed - In the catch block? Nuts! -Barry [ May 01, 2003: Message edited by: Barry Gaunt ]
In fact, I thinks, there is some typo in that thair example. The catch block should be empty, there's a missing right brace! The yield() and System.outprint() are supposed to be outside the empty catch block.
Yup, my trusty BlueJ reveals all. Missing right curly strikes again. (Old farts 1 : Others 0 ) [ May 01, 2003: Message edited by: Barry Gaunt ] [ May 01, 2003: Message edited by: Barry Gaunt ]
Johannes de Jong
Joined: Jan 27, 2001
Yep Barry you are right there should be a empty block after the catch. It is correct in Exam1. Unless Marcus went and changed it quickly
Cowgirl and Author
Joined: Oct 10, 2002
Howdy, Yes, I just assumed that the yield() and print statement were *outside* the catch block. Sorry, I should have mentioned that! cheers, Kathy
Joined: Dec 19, 2002
True, I goofed up while copying that part of the code. I knew this could pose a problem (taking attention away from the problem at hand) so I had a link to the mock test site too. Thanks Kathy for your excellent feedback, which clarified my doubt. Saket
Johannes de Jong
Joined: Jan 27, 2001
So basically its Old Farts 1 - Others 1 I gave away a goal Just an old mainframe-boy in a OO world