Android Best Practices Performance-multithreading

Source: Internet
Author: User

executing code on a separate thread

Address: http://developer.android.com/training/multiple-threads/define-runnable.html
The Runnable object is an interface that only has a run method. It simply represents a piece of code that can be executed.

To say this, it means that it is not necessarily performed in a child thread. It is also able to execute on the UI thread .

Suppose it is used to execute a piece of code, often referred to as a task.
The thread class and the Runnable class. are very powerful base classes, they are the foundation of the powerful Android base class Handlerthread, asynctask and Intentservice , and are also the basis of threadpoolexecutor.

This class proactively manages threads and task queues. You can even have multiple asynchronous tasks in parallel.

Define a runnable
public class PhotoDecodeRunnable implements Runnable {    ...    @Override    public void run() {        /*         * Code you want to run on the thread goes here         */        ...    }    ...}
implementing the Run () method

In design, Runnable objects are generally designed to be executed in a child thread, as in new thread (new runnable{}).
In the demo sample below. Start by calling the process.setthreadpriority () method and passing in the thread_priority_background. This reduces the resource contention between the Runnable object's thread and the UI thread.


You should also call Thread.CurrentThread (). Save a reference to the thread where runnable is located.

class PhotoDecodeRunnable implements Runnable {...    /*     for this task.     */    @Override    public void run() {        // Moves the current Thread into the background        android.os.Process.setThreadPriority(android.os.Process.THREAD_PRIORITY_BACKGROUND);        ...        /*         in the PhotoTask instance,         * so that the instance         * can interrupt the Thread.         */        mPhotoTask.setImageDecodeThread(Thread.currentThread());        ...    }...}
managing Multithreading

Address: http://developer.android.com/training/multiple-threads/create-threadpool.html
Suppose you only execute task (Runnable) Once, then the content of the previous article is sufficient; Suppose you want to execute a task repeatedly in a different dataset, but you can only perform one task,intentservice at a time to meet your needs. In order to proactively maximize the use of resources, or execute multiple tasks at the same time, you need a multithreaded management object. Using Threadpoolexecutor, which uses idle threads to execute a task in the queue, what you need to do is to add tasks to the queue.
A thread pool can execute multiple tasks in parallel, so you want to make sure that your code is thread-safe

define a thread pool objectUsing static variables for thread pooling

In the app, the thread pool may need a singleton:

public class PhotoManager {    ...    static  {        ...        // Creates a single static instance of PhotoManager        sInstance = new PhotoManager();    }    ...
Using private method of construction

If you privatize the construction method, you do not need to synchronized block to construct the closure method:

publicclass 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.     */    privatePhotoManager() {    ...    }
Using methods in the thread pool class to execute a task

Add a task to the queue in the online pool class:

public class PhotoManager {    ...    // Called by the PhotoView to get a photo    static public PhotoTask startDownload(        PhotoView imageView,        boolean cacheFlag) {        ...        for execution        sInstance.                mDownloadThreadPool.                execute(downloadTask.getHTTPDownloadRunnable());        ...    }
Initializing a handler on the UI thread
privatePhotoManager() {    ...        // Defines a Handler object that‘s attached to the UI thread        new Handler(Looper.getMainLooper()) {            /*             * handleMessage() defines the operations to perform when             * the Handler receives a new Message to process.             */            @Override            publicvoidhandleMessage(Message inputMessage) {                ...            }        ...        }    }
determining thread pool parameters

To initialize a threadpoolexecutor object, the following parameters are required:
1. Initialize the pool size and the largest pool size
The number of threads that can be used in a thread pool depends primarily on the number of CPU cores available to your device:

publicclass PhotoManager {...    /*     * Gets the number of available cores     * (not always the same as the maximum number of cores)     */    privatestaticint NUMBER_OF_CORES =            Runtime.getRuntime().availableProcessors();}

This number may not reflect the number of physical CPU cores on the device.

Some devices have shut down one or more cores depending on the load of the system, and for these devices, Availableprocessors () returns the number of cores available, which is typically less than the total number of cores.

2. Active time and Time unit
Active time is the time a thread keeps spare before it shuts down. The units of this time are determined by the constants in Timeunit .

3. Task Queue
Threadpoolexecutor holds a Runnable object in the task queue. When initializing Threadpoolexecutor, pass in a queue that implements the Blockingqueue interface. To meet app needs. You can choose an existing class that implements this interface, here's a sample of Linkedblockingqueue :

public class PhotoManager {    ...    private PhotoManager() {        ...        // A queue of Runnables        private final BlockingQueue<Runnable> mDecodeWorkQueue;        ...        // Instantiates the queue of Runnables as a LinkedBlockingQueue        mDecodeWorkQueue = new LinkedBlockingQueue<Runnable>();        ...    }    ...}
Create a pool of threads

Call Threadpoolexecutor's Construction Method Threadpoolexecutor () to create a thread pool:

  Private Photomanager() {        ...//sets the amount of time an idle thread waits before terminating        Private Static Final intKeep_alive_time =1;//sets the time Unit to seconds        Private Static FinalTimeunit keep_alive_time_unit = timeunit.seconds;//Creates a thread pool managerMdecodethreadpool =NewThreadpoolexecutor (Number_of_cores,//Initial Pool sizeNumber_of_cores,//Max Pool sizeKeep_alive_time, Keep_alive_time_unit, Mdecodeworkqueue); }

Full code Download Threadsample.zip

executing code on one thread of the online pool

Address: Http://developer.android.com/training/multiple-threads/run-code.html#StopThread
You add a task to the task queue, and the task in the queue is executed when the thread pool is spare. To conserve CPU resources, you can also interrupt a thread that is executing.

Executing code in a thread within a pool

Pass a Runnable to Threadpoolexecutor.execute () method, you can start a task. This method joins the task into the work queue of the thread pool, and when there is a spare thread, it takes out the tasks in the queue for execution:

public class PhotoManager {    public void handleState(PhotoTask photoTask, int state) {        switch (state) {            // The task finished downloading the image            case DOWNLOAD_COMPLETE:            // Decodes the image                mDecodeThreadPool.execute(                        photoTask.getPhotoDecodeRunnable());            ...        }        ...    }    ...}
interrupt (Interrupt) execution Code

To end a task. You need to interrupt the thread where the task is located. In order to be able to do so. When you create a task, you save a handle to the thread of the task:

class PhotoDecodeRunnable implements Runnable {    for this task    public void run() {        /*         in the         * object that contains PhotoDecodeRunnable         */        mPhotoTask.setImageDecodeThread(Thread.currentThread());        ...    }    ...}

Call Thread.Interrupt () to break a thread. Note that the thread object is controlled by the system. Ability to change them outside of the app process. Therefore, you need to lock the access in the thread before interrupting it, and add synchronized blocks of code where you are visiting. Like what:

 Public classPhotomanager { Public Static void Cancelall() {/* * Creates an array of runnables that's the same size as the * thread pool work Queue */runnable[] Runnablearray =NewRunnable[mdecodeworkqueue.size ()];//Populates the array with the runnables in the the queueMdecodeworkqueue.toarray (Runnablearray);//Stores the array length in order to iterate over the array        intlen = runnablearray.length;/* * Iterates over the array of runnables and interrupts each one's Thread. */Synchronized (sinstance) {//Iterates over the the tasks of the array             for(intRunnableindex =0; Runnableindex < Len; runnableindex++) {//Gets the current threadThread thread = Runnablearray[taskarrayindex].mthread;//If the Thread exists, post an interrupt to it                if(NULL! = thread) {thread.interrupt (); }            }        }    }    ...}

In most cases, thread.interrupt () will stop the thread directly. However, it will only stop waiting threads. Threads that are using CPU and network tasks are not interrupted. To prevent slowing down or locking down the system, you should infer that you are interrupted before you perform an operation:

/* * Before continuing, checks to see that the Thread hasn‘t * been interrupted */if (Thread.interrupted()) {    return;}...// Decodes a byte array into a Bitmap (CPU-intensive)BitmapFactory.decodeByteArray(        imageBuffer0imageBuffer.length, bitmapOptions);...

Full code Download Threadsample.zip

interaction of the UI thread

Address: http://developer.android.com/training/multiple-threads/communicate-ui.html
In Android, you typically use Handlerto send results to the UI thread in a child thread, and then manipulate the UI in the UI thread.

define a handler on the UI thread

Handler is part of the management thread in the Android framework. A handler object receives the message and then executes some code to process the messages.

In general, create a handler in a new thread, and you can create handler in an existing thread. When handler is created on the UI thread. Then the code it handles is also executed on the UI thread.
The Looper class is also part of the Android system management thread. This Looper object is passed into the handler constructor, and this handler executes on the thread where the Looper is located.

private PhotoManager() {...    // Defines a Handler object that‘s attached to the UI thread    mHandler = new Handler(Looper.getMainLooper()) {    ...

Overwrite the Handlemessage () method to handle handler messages sent from one thread.

        /*         * handleMessage() defines the operations to perform when         * the Handler receives a new Message to process.         */        @Override        public void handleMessage(Message inputMessage) {            // Gets the image task from the incoming Message object.            PhotoTask photoTask = (PhotoTask) inputMessage.obj;            ...        }    ...    next section shows how to tell the Handler to move data.
moving data from a task to the UI thread

In order to move data from the task executing in the background thread to the UI thread, we start by saving references to the data and UI objects in the task class. And then. Passes the Task object and the status code to the object that is instantiated by the handler. Then send a message containing the task and status code to handler.

Because handler executes on the UI thread. So it can send data to the UI object.

A class that decodes photo files into Bitmapsclass photodecoderunnable implements Runnable {...Photodecoderunnable (Phototask downloadtask) {mphototask = Downloadtask; }...Gets the downloaded byte array byte[] Imagebuffer = Mphototask.getbytebuffer ();...Runs the Code forThis task public void run () {...Tries to decode the image buffer Returnbitmap = Bitmapfactory.decodebytearray (Imagebuffer,0, Imagebuffer.length, bitmapoptions);...Sets the ImageView Bitmap mphototask.setimage (RETURNBITMAP); Reports a status of"Completed"Mphototask.handledecodestate (decode_state_completed);...}...}...

There are also ImageView and bitmap handles in the phototask .

Although they are in the same object, they cannot give bitmap to the ImageView display because they are not on the UI thread.

public class Phototask {...Gets a handle to the object that creates the thread pools Sphotomanager = Photomanager.getinstance ();...public void handledecodestate (int state) {int outstate; Converts the decode state to the overall state.Switch(state) {Case PhotoDecodeRunnable.DECODE_STATE_COMPLETED:outState = Photomanager.task_complete; Break;...}...Calls the generalized state Method Handlestate (outstate); }...Passes the state to Photomanager void handlestate (int state) {/* * Passes a handle to this task and The * Current state to the class that created * the thread pools */Sphotomanager.handlesta    Te (this, state); }...}

The

Photomanager receives a status code and a handle to a Phototask object, because the status is Task_complete , Create a message that includes the status and Task objects and then send to handler:

public class Photomanager { ...  Handle status messages from Tasks public void handlestate (Phototask phototask, int.) {switch  (state) {  The task finished downloading and decoding the image case Task_complete:/* *                 Creates a message for  the Handler * with the state and the Task object */Message Completemessage = Mhandler.obtainmessage (state, Phototask                );                Completemessage.sendtotarget ();            break ;         ...     }  ...  }

Finally, the state in the message is measured in handler.handlemessage () . Assuming that the state is Task_complete, the TASK is complete. The ImageView in the phototask need to display the bitmap objects in them. Because handler.handlemessage () executes on the UI thread, now ImageView shows bitmap is agreed.

Android Best Practices Performance-multithreading

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.