Thread Mania


To get a better idea what is going on with thread in in this chapter I instrumented my code with log statements that included the thread id:

It was quite informative. It appears that although queueThumbnail is a method of the ThumbDownloaderHandler (TD), it executes in the context of the main thread that runs the UI for the fragment/activity. When queueThumbnail issues the obtainMessage and sendToTarget, it is doing so on the mHandler of the TD - this is because mHandler was instantiated in method onLoopPrepared of the TD thread, which implicitly associates the handler mHandler with the TD thread. Thus issuing mHandler.sendToTarget actually enqueues the message on the message queue of the TD thread FROM the main UI thread context.

This was not obvious to me although I guess the chapter described the capability but not in the clearest of terms from a tasking context perspective (I’m an old OS systems programmer trying to live in app-land so cut me a break!)

Additionally when the TD thread handles a message, it directly invokes the getUrlBytes method in the FlickrFetchr class which waits for the HTTP request to Flickr for the thumbnail to complete, then its last duty (before returning to looper) is to inform the main thread the Thumbnail download requested is completed by using the mResponseHandler. The handleRequest method is running in the context of the TD thread and its last act is to invoke the post() method of the mResponseHandler, which causes the runnable passed in as a parameter to post() to be scheduled for execution on the main thread. The next time the main thread runs it executes the runnable on the main thread and it invokes the previously setup Listener back in the fragment which shoves the bitmap to the view. This is all enabled by having the main thread pass in its handler on creation of the TD thread, to use as a hook for driving code to run in the Main thread to process the result (mResultHandler).

Looking at the threadids really helped understand the tasking aspects and the IPC! Great chapter!


One additional question on the bitmap returned in handleRequest. I notice the bitmap is a “final” variable - isn’t the bitmap stored in a local variable of the TD thread stack? How is the bitmap itself ultimately copied to the main task? I see the runnable utilizes it even though the runnable itself will run in the context of the main thread. While I recognize the threads share the processes memory each one does have its own stack - how does the bitmap variable get to where the main thread can access it and persist as needed? Is it copied by the runtime because runnable is an instance of an anonymous class? Is this also why it must be declared final so it informs the compiler how to handle it?

  1. Thanks for the suggestion to track the threadID’s, it’s fun and informative to see the real-time execution of each function in each thread.

  2. Regarding final: - See “Final and inner classes”.

If you take away final in front of the Bitmap (“bitmap”) variable, you’ll get your exact answer from the compiler.
“Cannot refer to a non-final variable bitmap inside an inner class defined in a different method.”

When the handleRequest() method returns, your local variable “bitmap” will be cleaned up from the stack, so it won’t exist anymore. But the anonymous class object “new Runnable()…” references that variable. After it is declared final, the Object reference cannot be change, and it is captured as a local copy for the anonymous inner class in its own memory, even after the original handleRequest’s stack has been cleaned up.