Thread Is One of The Important Concepts in Android

You might also like

Download as docx, pdf, or txt
Download as docx, pdf, or txt
You are on page 1of 10

Thread is one of the important concepts in Android.

Thread is a lightweight sub-process that


provides us a way to do background operations without interrupting the User Interface (UI).
When an app is launched, it creates a single thread in which all app components will run by
default. The thread which is created by the runtime system is known as the main thread. The
main thread’s primary role is to handle the UI in terms of event handling and interaction with
views in the UI. If there is a task that is time-consuming and that task is run on the main thread,
then it will stop other tasks until it gets completed, which in turn may result in displaying a
warning “Application is unresponsive” to the user by the operating system. So we need different
threads for such tasks and some other tasks.

avoid network operations, database calls, and the loading of certain components in the main
thread. Because the main thread is called synchronously when executed, that means the user
interface will remain completely unresponsive until the performance completes.

All threading components belong to one of two basic categories.

The fragment or activity attached threads: This category of threads are bound to the
lifecycle of the activity/fragment and these are terminated as soon as the
activity/fragment is destroyed.
Thread components:
AsyncTask, Loaders.
 The fragment or activity not attached threads: These types of threads can continue to
run beyond the lifetime of the activity or fragment from which they were spawned.

Threading Components: Service, Intent Service.


For the two threading components, there are five types of thread used in Android mobile
development.

 Main Thread: When we launch our app on Android, it creates the first thread of
execution called the “Main Thread”. The communication between the components from
the Android UI toolkit and the dispatching of events to their appropriate UI widgets is
handled by the main thread. We should

 UI Thread: Every app in Android has its own thread which is responsible for running the UI
objects, like view objects. Such a thread is known as the UI thread. The UI thread is the main
thread of execution for our app as this is where most of the app code is run. The UI thread is
where all of our app components (like activities, services, content providers, and broadcast
receivers) are created. This thread allows our tasks to perform their background work and then
move the results to UI elements such as bitmaps. All objects running on our UI thread will be
able to access other objects which are also running on the same UI thread. The tasks that we run
on a thread from a thread pool do not run on our UI thread, so they will not have access to UI
objects. The data moves from a background thread to the UI thread, using a handler that runs on
the UI thread.

 Worker Thread: The worker thread is a background thread. The worker threads are created
separately, other than threads like the UI thread. As we know from the rules, we cannot block a
UI thread so this is where the worker thread comes into play since we can use them to run the
child processes and tasks.

Binder Thread: Binder thread represents a separate thread of service. The binder is a mechanism that
provides inter-process communication. The binder thread is used in service binding with interprocess
communication. This concept is mainly related to service calls with interfaces defined by Android
Interface Definition Language (AIDL).

How Does Threading Work in Android?


When an application is launched in Android, it creates the primary thread of execution, referred
to as the “main” thread. Most thread is liable for dispatching events to the acceptable interface
widgets also as communicating with components from the Android UI toolkit. To keep your
application responsive, it’s essential to avoid using the most thread to perform any operation
which will find yourself keeping it blocked.

Network operations and database calls, also as loading of certain components, are common
samples of operations that one should avoid within the main thread. Once they are called within
the main thread, they’re called synchronously, which suggests that the UI will remain completely
unresponsive until the operation completes. Due to this, tasks requiring calls are usually
performed in different threads, which in turn avoids blocking the UI and keeps it responsive
while the tasks are being performed. (i.e., they’ve performed asynchronously from the UI).

Android provides some ways of making and managing threads, and lots of third-party libraries
exist that make thread management tons more pleasant. However, with numerous approaches at
hand, choosing the proper one are often quite confusing. In this article, you’ll study some
common scenarios in Android development where threading becomes essential and a few
simple solutions which will be applied to those scenarios and more.

Threading in Android

in Android, you’ll categorize all threading components into two basic categories:

1. Threads that are attached to an activity/fragment: These threads are tied to the
lifecycle of the activity/fragment and are terminated as soon because the
activity/fragment is destroyed.
2. Threads that aren’t attached to any activity/fragment: These threads can still run
beyond the lifetime of the activity/fragment (if any) from which they were spawned.

Multi-threading is one of the most valued concepts in any programming language. Making adept
use of threads on Android can help you boost your app’s performance.
When a user opens an application, Android creates its own Linux process. Besides this, the
system creates a thread of execution for that application called the main thread or UI thread.

The main thread is nothing but a handler thread. The main thread is responsible for handling
events from all over the app like callbacks associated with the lifecycle information or callbacks
from input events or handling events from other apps, etc.

Any block of code that needs to be run is pushed into a work queue and then serviced by the main
thread. As the main thread does so much work, it’s better to offer longer work to other threads, so as
not to disturb the UI thread from its rendering duties.

Basic Thread Management

There are four basic thread management operations: thread creation, thread termination, thread
join, and thread yield.

Thread Creation

We have discussed the creation of threads in a previous page. Basically, we can split the
execution thread into two. After this, both threads execute concurrently. The creating thread is
the parent thread, and the created thread is a child thread. Note that any thread, including the
main program which is run as a thread when it starts, can create child threads at any time. In the
following diagram, Thread A runs initially. Sometime later, it creates Thread B as indicated
by a yellow dot. After this creation, Thread A and Thread B runs concurrently. Later on,
Thread A may create one more thread Thread C. After Thread C is created, there are three
threads running concurrently, all of which compete to use the CPUs. However, which thread is
run at a particular time is not known to any one of them. The quicksort example discussed on a
previous page employs this scheme, where Thread A receives an array segment, partitions it
into two segments, creates Thread B to sort the left segment, and then creates Thread C to sort
the right one. Or, after the given array segment is partitioned into two, Thread A creates
Thread B to sort the left segment and sorts the right segment by itself. In this way, two threads,
one parent - Thread A - and one child - Thread B - would be sufficient.
Thread Termination

For most of the cases, threads are not created and run forever. After finish their work, threads
terminate. In the quicksort example, after both array subsegments are sorted, the threads created
for sorting them terminate. In fact, the thread that creates these two child threads terminates too,
because its assigned task completes. In the merging example, the threads created to determine
the position of array elements a[i] and b[j] in the merged array terminate once the final positions
are computed. Similarly, in the matrix multiplication example, once the value of C[i,j] is
computed, the corresponding thread terminates. In general, when the assigned task of a thread
completes, the thread may be terminated.

Moreover, if the parent thread terminates, all of its child threads terminate as well.
Why is this important? We briefly mentioned in a previous page that the child threads share
resources with the parent thread, including variables. When the parent thread terminates, all of its
variables are gone, and, as a result, the child threads will not be able to access to those resources
that the parent thread owns. Thus, if the parent thread runs faster and terminates earlier than its
child threads do, we have a problem! This is why we need the third thread management feature:
thread join.

Thread Join

Imagine the following scenario. You are preparing for tomorrow's final examine and feel a little
hungry. So, you give your younger brother ten bucks and ask him to buy a pizza for you. In this
case, you are the main thread and your brother is a child thread. Once your order is given, both
you and your brother are doing their job concurrently (i.e., studying and buying a pizza). Now,
we have two cases to consider. First, your brother brings your pizza back and terminates while
you are studying. In this case, you can stop studying and enjoy the pizza. Second, you finish
your study early and sleep (i.e., your assigned job for today - study for tomorrow's final exam - is
done) before the pizza is available. Of course, you cannot sleep; otherwise, you won't have a
chance to eat the pizza. What you are going to do is to wait until your brother brings the pizza
back. This is exactly the problem and solution we mentioned at the end of the previous section.

Thread join is designed to solve this problem. A thread can execute a thread join to wait until the
other thread terminates. In our case, you - the main thread - should execute a thread join waiting
for your brother - a child thread - to terminate. In general, thread join is for a parent to
join with one of its child threads. Thread join has the following activities, assuming that a
parent thread P wants to join with one of its child threads C.

 When P executes a thread join in order to join with C, which is still running, P is suspended until
C terminates. Once C terminates, P resumes.
 When P executes a thread join and C has already terminated, P continues as if no such thread
join has ever executed (i.e., join has no effect).

A parent thread may join with many child threads created by the parent. Or, a parent only join with
some of its child threads, and ignore other child threads. In this case, those child threads that are
ignored by the parent will be terminated when the parent terminates.
Thread Yield

Suppose you run a number of programs at the same time on a computer. It is possible that some
CPU hogs keep eating up the CPU cycles so that other programs may hardly run. Well, this may
be a problem of the scheduling policy of the operating system. However, when we write our
programs with multiple threads, we have to make sure that some threads will not occupy the
CPU forever, or for a very long time, without relinquishing it. Otherwise, we will end up in the
situation where one or two threads keep running while the others simply wait there for their
turns. That is, we run our threads in a very ``polite'' way that once a while a thread takes some
rest so that the CPU can be used by other threads. This is achieved by thread yield.

When a thread executes a thread yield, the executing thread is suspended and the CPU is given to
some other runnable thread. This thread will wait until the CPU becomes available again.
Technically, in process scheduler's terminology, the executing thread is put back into the ready
queue of the processor and waits for its next turn. The following shows an example, where a
small circle indicates the execution of a thread yield, a small square means the control is
transferred back, a solid arrow indicates thread execution, and a dashed line segment depicts a
thread waiting for execution. Suppose we have three threads A, B and C. Initially, A is running
and executes a thread yield sometime later. This causes A is suspended temporarily and the CPU
is given to the next thread, say B. Then, B runs for a while and executes a thread yield. Because
there are two threads that are ready to run, A and C, the thread system picks one to run. Suppose
it is C. When C executes a thread join, the control may switch back to A or B; however, the
diagram shows the control is given back to A. In this way, threads execute in a cooperative way.

Thread Suspend and Resume

Thread suspend and resume are two more thread management features. When a thread executes a
thread suspend to suspend the execution of itself or another thread, the indicated thread will be
suspended until the execution of a thread resume that releases the indicated thread. For example,
suppose we have three threads A, B and C running concurrently. Then, thread A execute a thread
suspend to suspend the execution of thread B. After this, we have only two threads A and C
running concurrently. Note that even though both A and C are waiting for the completion of their
own I/O activities and no thread is running, the suspended thread B cannot run. To run thread B
again, one of the other threads must execution a corresponding thread resume. For example,
thread C may execute a thread resume to resume thread B's execution. After this, all three threads
are running concurrently.

Both thread yield and thread suspend cause the execution of a thread to be suspended. What is
the difference? The difference is a big one! With thread yield, the yielding thread is put back to
the ready queue and will run when its turn comes. Thus, a yielding thread is runnable if the CPU
becomes free in the future, although it is suspended. With a thread suspend, the suspended thread
is not i Thread Termination

For most of the cases, threads are not created and run forever. After finish their work, threads
terminate. In the quicksort example, after both array subsegments are sorted, the threads created
for sorting them terminate. In fact, the thread that creates these two child threads terminates too,
because its assigned task completes. In the merging example, the threads created to determine the
position of array elements a[i] and b[j] in the merged array terminate once the final positions are
computed. Similarly, in the matrix multiplication example, once the value of C[i,j] is computed,
the corresponding thread terminates. In general, when the assigned task of a thread completes,
the thread may be terminated.

Moreover, if the parent thread terminates, all of its child threads terminate as well. Why is this
important? We briefly mentioned in a previous page that the child threads share resources with
the parent thread, including variables. When the parent thread terminates, all of its variables are
gone, and, as a result, the child threads will not be able to access to those resources that the
parent thread owns. Thus, if the parent thread runs faster and terminates earlier than its child
threads do, we have a problem! This is why we need the third thread management feature: thread
join.

Thread Join

Imagine the following scenario. You are preparing for tomorrow's final examine and feel a little
hungry. So, you give your younger brother ten bucks and ask him to buy a pizza for you. In this
case, you are the main thread and your brother is a child thread. Once your order is given, both
you and your brother are doing their job concurrently (i.e., studying and buying a pizza). Now,
we have two cases to consider. First, your brother brings your pizza back and terminates while
you are studying. In this case, you can stop studying and enjoy the pizza. Second, you finish your
study early and sleep (i.e., your assigned job for today - study for tomorrow's final exam - is
done) before the pizza is available. Of course, you cannot sleep; otherwise, you won't have a
chance to eat the pizza. What you are going to do is to wait until your brother brings the pizza
back. This is exactly the problem and solution we mentioned at the end of the previous section.

Thread join is designed to solve this problem. A thread can execute a thread join to wait until the
other thread terminates. In our case, you - the main thread - should execute a thread join waiting
for your brother - a child thread - to terminate. In general, thread join is for a parent to join with
one of its child threads. Thread join has the following activities, assuming that a parent thread P
wants to join with one of its child threads C.

When P executes a thread join in order to join with C, which is still running, P is suspended
until C terminates. Once C terminates, P resumes.

When P executes a thread join and C has already terminated, P continues as if no such thread
join has ever executed (i.e., join has no effect).

A parent thread may join with many child threads created by the parent. Or, a parent only join
with some of its child threads, and ignore other child threads. In this case, those child threads that
are ignored by the parent will be terminated when the parent terminates.

Thread Yield

Suppose you run a number of programs at the same time on a computer. It is possible that some
CPU hogs keep eating up the CPU cycles so that other programs may hardly run. Well, this may
be a problem of the scheduling policy of the operating system. However, when we write our
programs with multiple threads, we have to make sure that some threads will not occupy the
CPU forever, or for a very long time, without relinquishing it. Otherwise, we will end up in the
situation where one or two threads keep running while the others simply wait there for their
turns. That is, we run our threads in a very ``polite'' way that once a while a thread takes some
rest so that the CPU can be used by other threads. This is achieved by thread yield.

When a thread executes a thread yield, the executing thread is suspended and the CPU is given to
some other runnable thread. This thread will wait until the CPU becomes available again.
Technically, in process scheduler's terminology, the executing thread is put back into the ready
queue of the processor and waits for its next turn. The following shows an example, where a
small circle indicates the execution of a thread yield, a small square means the control is
transferred back, a solid arrow indicates thread execution, and a dashed line segment depicts a
thread waiting for execution. Suppose we have three threads A, B and C. Initially, A is running
and executes a thread yield sometime later. This causes A is suspended temporarily and the CPU
is given to the next thread, say B. Then, B runs for a while and executes a thread yield. Because
there are two threads that are ready to run, A and C, the thread system picks one to run. Suppose
it is C. When C executes a thread join, the control may switch back to A or B; however, the
diagram shows the control is given back to A. In this way, threads execute in a cooperative way.

Thread Suspend and Resume

Thread suspend and resume are two more thread management features. When a thread executes a
thread suspend to suspend the execution of itself or another thread, the indicated thread will be
suspended until the execution of a thread resume that releases the indicated thread. For example,
suppose we have three threads A, B and C running concurrently. Then, thread A execute a thread
suspend to suspend the execution of thread B. After this, we have only two threads A and C
running concurrently. Note that even though both A and C are waiting for the completion of their
own I/O activities and no thread is running, the suspended thread B cannot run. To run thread B
again, one of the other threads must execution a corresponding thread resume. For example,
thread C may execute a thread resume to resume thread B's execution. After this, all three threads
are running concurrently.

Both thread yield and thread suspend cause the execution of a thread to be suspended. What is
the difference? The difference is a big one! With thread yield, the yielding thread is put back to
the ready queue and will run when its turn comes. Thus, a yielding thread is runnable if the CPU
becomes free in the future, although it is suspended. With a thread suspend, the suspended thread
is not in the ready queue, and, as a result, the scheduler will not be able to pick it up and let it run
when the CPU becomes free. Instead, the execution of a suspended thread can be resumed only
by a specific thread resume call.

Thread suspend/resume can be very useful. For example, suppose a program must handle five
different tasks. The main program may create five threads, one for each task. Initially, all threads
are suspended by the main program. Once a task comes, the main program just resumes the
corresponding thread. After handling the task, the thread simply suspends itself. This may be
more efficient that creating a new thread to handle the task and then terminating the thread.
However, thread suspend and resume could post some problem. Suppose a thread acquire a lock
so that it becomes the only thread that can access to a shared resource. If before the thread
releases the lock, it is suspended by another thread. Should this happen, no other thread can
access the shared resource until a thread resume the suspended thread for it to release the lock.
Because of this potential problem, which may lead to a system deadlock, the use of thread
suspend and resume is usually not recommended. Some systems such as the Pthread do not
support thread suspend and resume. n the ready queue, and, as a result, the scheduler will not be
able to pick it up and let it run when the CPU becomes free. Instead, the execution of a
suspended thread can be resumed only by a specific thread resume call.

Thread suspend/resume can be very useful. For example, suppose a program must handle five
different tasks. The main program may create five threads, one for each task. Initially, all threads
are suspended by the main program. Once a task comes, the main program just resumes the
corresponding thread. After handling the task, the thread simply suspends itself. This may be
more efficient that creating a new thread to handle the task and then terminating the thread.
However, thread suspend and resume could post some problem. Suppose a thread acquire a lock
so that it becomes the only thread that can access to a shared resource. If before the thread
releases the lock, it is suspended by another thread. Should this happen, no other thread can
access the shared resource until a thread resume the suspended thread for it to release the lock.
Because of this potential problem, which may lead to a system deadlock, the use of thread
suspend and resume is usually not recommended. Some systems such as the Pthread do not
support thread suspend and resume.

You might also like