summaryrefslogtreecommitdiffstats
path: root/docs/html/training/multiple-threads/create-threadpool.jd
diff options
context:
space:
mode:
authorJoe Malin <jmalin@google.com>2012-11-26 14:06:35 -0800
committerJoe Malin <jmalin@google.com>2012-12-19 09:47:04 -0800
commit8dd6275e2871bea1acb20cbdd98ea0451b3d5be0 (patch)
tree51efc474f81e56f646c2f815e9c919abc2a7a80d /docs/html/training/multiple-threads/create-threadpool.jd
parentba34f097df278ce1861ebfecdaf634f519ba1f36 (diff)
downloadframeworks_base-8dd6275e2871bea1acb20cbdd98ea0451b3d5be0.zip
frameworks_base-8dd6275e2871bea1acb20cbdd98ea0451b3d5be0.tar.gz
frameworks_base-8dd6275e2871bea1acb20cbdd98ea0451b3d5be0.tar.bz2
Android Training: Multiple Threads
Change-Id: I58c472aa5ed82f6b4fb50d9bbb4e66841b9e99c3
Diffstat (limited to 'docs/html/training/multiple-threads/create-threadpool.jd')
-rw-r--r--docs/html/training/multiple-threads/create-threadpool.jd238
1 files changed, 238 insertions, 0 deletions
diff --git a/docs/html/training/multiple-threads/create-threadpool.jd b/docs/html/training/multiple-threads/create-threadpool.jd
new file mode 100644
index 0000000..4a4ddb1
--- /dev/null
+++ b/docs/html/training/multiple-threads/create-threadpool.jd
@@ -0,0 +1,238 @@
+page.title=Creating a Manager for Multiple Threads
+
+trainingnavtop=true
+@jd:body
+
+<div id="tb-wrapper">
+<div id="tb">
+
+<!-- table of contents -->
+<h2>This lesson teaches you to</h2>
+<ol>
+ <li><a href="#ClassStructure">Define the Thread Pool Class</a>
+ <li><a href="#PoolParameters">Determine the Thread Pool Parameters</a></li>
+ <li><a href="#ThreadPool">Create a Pool of Threads</a></li>
+</ol>
+
+<!-- other docs (NOT javadocs) -->
+<h2>You should also read</h2>
+<ul>
+ <li><a href="{@docRoot}guide/components/processes-and-threads.html">Processes and Threads</a></li>
+</ul>
+
+<h2>Try it out</h2>
+<div class="download-box">
+ <a href="{@docRoot}shareables/training/ThreadSample.zip" class="button">Download the sample</a>
+ <p class="filename">ThreadSample.zip</p>
+</div>
+
+
+</div>
+</div>
+
+<p>
+ The previous lesson showed how to define a task that executes on a
+ separate thread. If you only want to run the task once, this may be all you need. If you want
+ to run a task repeatedly on different sets of data, but you only need one execution running at a
+ time, an {@link android.app.IntentService} suits your needs. To automatically run tasks
+ as resources become available, or to allow multiple tasks to run at the same time (or both),
+ you need to provide a managed collection of threads. To do this, use an instance of
+ {@link java.util.concurrent.ThreadPoolExecutor}, which runs a task from a queue when a thread
+ in its pool becomes free. To run a task, all you have to do is add it to the queue.
+</p>
+<p>
+ A thread pool can run multiple parallel instances of a task, so you should ensure that your
+ code is thread-safe. Enclose variables that can be accessed by more than one thread in a
+ <code>synchronized</code> block. This approach will prevent one thread from reading the variable
+ while another is writing to it. Typically, this situation arises with static variables, but it
+ also occurs in any object that is only instantiated once. To learn more about this, read the
+ <a href="{@docRoot}http://developer.android.com/guide/components/processes-and-threads.html">
+ Processes and Threads</a> API guide.
+
+</p>
+<h2 id="ClassStructure">Define the Thread Pool Class</h2>
+<p>
+ Instantiate {@link java.util.concurrent.ThreadPoolExecutor} in its own class. Within this class,
+ do the following:
+</p>
+<dl>
+ <dt>
+ Use static variables for thread pools
+ </dt>
+ <dd>
+ You may only want a single instance of a thread pool for your app, in order to have a
+ single control point for restricted CPU or network resources. If you have different
+ {@link java.lang.Runnable} types, you may want to have a thread pool for each one, but each
+ of these can be a single instance. For example, you can add this as part of your
+ global field declarations:
+<pre>
+public class PhotoManager {
+ ...
+ static {
+ ...
+ // Creates a single static instance of PhotoManager
+ sInstance = new PhotoManager();
+ }
+ ...
+</pre>
+ </dd>
+ <dt>
+ Use a private constructor
+ </dt>
+ <dd>
+ Making the constructor private ensures that it is a singleton, which means that you don't
+ have to enclose accesses to the class in a <code>synchronized</code> block:
+<pre>
+public class PhotoManager {
+ ...
+ /**
+ * Constructs the work queues and thread pools used to download
+ * and decode images. Because the constructor is marked private,
+ * it's unavailable to other classes, even in the same package.
+ */
+ private PhotoManager() {
+ ...
+ }
+</pre>
+ </dd>
+ <dt>
+ Start your tasks by calling methods in the thread pool class.
+ </dt>
+ <dd>
+ Define a method in the thread pool class that adds a task to a thread pool's queue. For
+ example:
+<pre>
+public class PhotoManager {
+ ...
+ // Called by the PhotoView to get a photo
+ static public PhotoTask startDownload(
+ PhotoView imageView,
+ boolean cacheFlag) {
+ ...
+ // Adds a download task to the thread pool for execution
+ sInstance.
+ mDownloadThreadPool.
+ execute(downloadTask.getHTTPDownloadRunnable());
+ ...
+ }
+</pre>
+ </dd>
+ <dt>
+ Instantiate a {@link android.os.Handler} in the constructor and attach it to your app's
+ UI thread.
+ </dt>
+ <dd>
+ A {@link android.os.Handler} allows your app to safely call the methods of UI objects
+ such as {@link android.view.View} objects. Most UI objects may only be safely altered from
+ the UI thread. This approach is described in more detail in the lesson
+ <a href="communicate-ui.html">Communicate with the UI Thread</a>. For example:
+<pre>
+ private PhotoManager() {
+ ...
+ // Defines a Handler object that's attached to the UI thread
+ mHandler = new Handler(Looper.getMainLooper()) {
+ /*
+ * handleMessage() defines the operations to perform when
+ * the Handler receives a new Message to process.
+ */
+ &#64;Override
+ public void handleMessage(Message inputMessage) {
+ ...
+ }
+ ...
+ }
+ }
+</pre>
+ </dd>
+</dl>
+<h2 id="PoolParameters">Determine the Thread Pool Parameters</h2>
+<p>
+ Once you have the overall class structure, you can start defining the thread pool. To
+ instantiate a {@link java.util.concurrent.ThreadPoolExecutor} object, you need the
+ following values:
+</p>
+<dl>
+ <dt>
+ Initial pool size and maximum pool size
+ </dt>
+ <dd>
+ The initial number of threads to allocate to the pool, and the maximum allowable number.
+ The number of threads you can have in a thread pool depends primarily on the number of cores
+ available for your device. This number is available from the system environment:
+<pre>
+public class PhotoManager {
+...
+ /*
+ * Gets the number of available cores
+ * (not always the same as the maximum number of cores)
+ */
+ private static int NUMBER_OF_CORES =
+ Runtime.getRuntime().availableProcessors();
+}
+</pre>
+ This number may not reflect the number of physical cores in the device; some devices have
+ CPUs that deactivate one or more cores depending on the system load. For these devices,
+ {@link java.lang.Runtime#availableProcessors availableProcessors()} returns the number of
+ <i>active</i> cores, which may be less than the total number of cores.
+ </dd>
+ <dt>
+ Keep alive time and time unit
+ </dt>
+ <dd>
+ The duration that a thread will remain idle before it shuts down. The duration is
+ interpreted by the time unit value, one of the constants defined in
+ {@link java.util.concurrent.TimeUnit}.
+ </dd>
+ <dt>
+ A queue of tasks
+ </dt>
+ <dd>
+ The incoming queue from which {@link java.util.concurrent.ThreadPoolExecutor} takes
+ {@link java.lang.Runnable} objects. To start code on a thread, a thread pool manager takes a
+ {@link java.lang.Runnable} object from a first-in, first-out queue and attaches it to the
+ thread. You provide this queue object when you create the thread pool, using any queue class
+ that implements the {@link java.util.concurrent.BlockingQueue} interface. To match the
+ requirements of your app, you can choose from the available queue implementations; to learn
+ more about them, see the class overview for {@link java.util.concurrent.ThreadPoolExecutor}.
+ This example uses the {@link java.util.concurrent.LinkedBlockingQueue} class:
+<pre>
+public class PhotoManager {
+ ...
+ private PhotoManager() {
+ ...
+ // A queue of Runnables
+ private final BlockingQueue&lt;Runnable&gt; mDecodeWorkQueue;
+ ...
+ // Instantiates the queue of Runnables as a LinkedBlockingQueue
+ mDecodeWorkQueue = new LinkedBlockingQueue&lt;Runnable&gt;();
+ ...
+ }
+ ...
+}
+</pre>
+ </dd>
+</dl>
+<h2 id="ThreadPool">Create a Pool of Threads</h2>
+<p>
+ To create a pool of threads, instantiate a thread pool manager by calling
+ {@link java.util.concurrent.ThreadPoolExecutor#ThreadPoolExecutor ThreadPoolExecutor()}.
+ This creates and manages a constrained group of threads. Because the initial pool size and
+ the maximum pool size are the same, {@link java.util.concurrent.ThreadPoolExecutor} creates
+ all of the thread objects when it is instantiated. For example:
+</p>
+<pre>
+ private PhotoManager() {
+ ...
+ // Sets the amount of time an idle thread waits before terminating
+ private static final int KEEP_ALIVE_TIME = 1;
+ // Sets the Time Unit to seconds
+ private static final TimeUnit KEEP_ALIVE_TIME_UNIT = TimeUnit.SECONDS;
+ // Creates a thread pool manager
+ mDecodeThreadPool = new ThreadPoolExecutor(
+ NUMBER_OF_CORES, // Initial pool size
+ NUMBER_OF_CORES, // Max pool size
+ KEEP_ALIVE_TIME,
+ KEEP_ALIVE_TIME_UNIT,
+ mDecodeWorkQueue);
+ }
+</pre>