Home | History | Annotate | Download | only in multiple-threads
      1 page.title=Running Code on a Thread Pool Thread
      2 
      3 trainingnavtop=true
      4 @jd:body
      5 
      6 <div id="tb-wrapper">
      7 <div id="tb">
      8 
      9 <!-- table of contents -->
     10 <h2>This lesson teaches you to</h2>
     11 <ol>
     12   <li><a href="#RunRunnable">Run a Runnable on a Thread in the Thread Pool</a></li>
     13   <li><a href="#StopThread">Interrupt Running Code</a></li>
     14 </ol>
     15 
     16 <h2>You should also read</h2>
     17 <ul>
     18   <li><a href="{@docRoot}guide/components/processes-and-threads.html">Processes and Threads</a></li>
     19 </ul>
     20 
     21 
     22 <h2>Try it out</h2>
     23 <div class="download-box">
     24     <a href="{@docRoot}shareables/training/ThreadSample.zip" class="button">Download the sample</a>
     25     <p class="filename">ThreadSample.zip</p>
     26 </div>
     27 
     28 </div>
     29 </div>
     30 
     31 <p>
     32     The previous lesson showed you how to define a class that manages thread pools and the tasks
     33     that run on them. This lesson shows you how to run a task on a thread pool. To do this,
     34     you add the task to the pool's work queue. When a thread becomes available, the
     35     {@link java.util.concurrent.ThreadPoolExecutor} takes a task from the queue and runs it on the
     36     thread.
     37 </p>
     38 <p>
     39     This lesson also shows you how to stop a task that's running. You might want to do this if a
     40     task starts, but then discovers that its work isn't necessary. Rather than wasting processor
     41     time, you can cancel the thread the task is running on. For example, if you are downloading
     42     images from the network and using a cache, you probably want to stop a task if it detects that
     43     an image is already present in the cache. Depending on how you write your app, you may not be
     44     able to detect this before you start the download.
     45 </p>
     46 <h2 id="RunRunnable">Run a Task on a Thread in the Thread Pool</h2>
     47 <p>
     48     To start a task object on a thread in a particular thread pool, pass the
     49     {@link java.lang.Runnable} to {@link java.util.concurrent.ThreadPoolExecutor#execute
     50     ThreadPoolExecutor.execute()}. This call adds the task to the thread pool's work queue. When an
     51     idle thread becomes available, the manager takes the task that has been waiting the longest and
     52     runs it on the thread:
     53 </p>
     54 <pre>
     55 public class PhotoManager {
     56     public void handleState(PhotoTask photoTask, int state) {
     57         switch (state) {
     58             // The task finished downloading the image
     59             case DOWNLOAD_COMPLETE:
     60             // Decodes the image
     61                 mDecodeThreadPool.execute(
     62                         photoTask.getPhotoDecodeRunnable());
     63             ...
     64         }
     65         ...
     66     }
     67     ...
     68 }
     69 </pre>
     70 <p>
     71     When {@link java.util.concurrent.ThreadPoolExecutor} starts a {@link java.lang.Runnable} on a
     72     thread, it automatically calls the object's {@link java.lang.Runnable#run run()} method.
     73 </p>
     74 <h2 id="StopThread">Interrupt Running Code</h2>
     75 <p>
     76     To stop a task, you need to interrupt the task's thread. To prepare to do this, you need to
     77     store a handle to the task's thread when you create the task. For example:
     78 </p>
     79 <pre>
     80 class PhotoDecodeRunnable implements Runnable {
     81     // Defines the code to run for this task
     82     public void run() {
     83         /*
     84          * Stores the current Thread in the
     85          * object that contains PhotoDecodeRunnable
     86          */
     87         mPhotoTask.setImageDecodeThread(Thread.currentThread());
     88         ...
     89     }
     90     ...
     91 }
     92 </pre>
     93 <p>
     94     To interrupt a thread, call {@link java.lang.Thread#interrupt Thread.interrupt()}. Notice that
     95     {@link java.lang.Thread} objects are controlled by the system, which can modify them outside of
     96     your app's process. For this reason, you need to lock access on a thread before you
     97     interrupt it, by placing the access in a <code>synchronized</code> block. For example:
     98 </p>
     99 <pre>
    100 public class PhotoManager {
    101     public static void cancelAll() {
    102         /*
    103          * Creates an array of Runnables that's the same size as the
    104          * thread pool work queue
    105          */
    106         Runnable[] runnableArray = new Runnable[mDecodeWorkQueue.size()];
    107         // Populates the array with the Runnables in the queue
    108         mDecodeWorkQueue.toArray(runnableArray);
    109         // Stores the array length in order to iterate over the array
    110         int len = runnableArray.length;
    111         /*
    112          * Iterates over the array of Runnables and interrupts each one's Thread.
    113          */
    114         synchronized (sInstance) {
    115             // Iterates over the array of tasks
    116             for (int runnableIndex = 0; runnableIndex &lt; len; runnableIndex++) {
    117                 // Gets the current thread
    118                 Thread thread = runnableArray[taskArrayIndex].mThread;
    119                 // if the Thread exists, post an interrupt to it
    120                 if (null != thread) {
    121                     thread.interrupt();
    122                 }
    123             }
    124         }
    125     }
    126     ...
    127 }
    128 </pre>
    129 <p>
    130     In most cases, {@link java.lang.Thread#interrupt Thread.interrupt()} stops the thread
    131     immediately. However, it only stops threads that are waiting, and will not interrupt CPU or
    132     network-intensive tasks. To avoid slowing down or locking up the system, you should test for
    133     any pending interrupt requests before attempting an operation :
    134 </p>
    135 <pre>
    136 /*
    137  * Before continuing, checks to see that the Thread hasn't
    138  * been interrupted
    139  */
    140 if (Thread.interrupted()) {
    141     return;
    142 }
    143 ...
    144 // Decodes a byte array into a Bitmap (CPU-intensive)
    145 BitmapFactory.decodeByteArray(
    146         imageBuffer, 0, imageBuffer.length, bitmapOptions);
    147 ...
    148 </pre>
    149