[MUSIC PLAYING]
Let's be honest, you're an awesome engineer
with an awesome app, and you are using threading to the max.
Sadly though, managing all those individual threads
and assigning work between them is
causing you to lose your hair.
My name is Colt McAnlis, and please,
don't join the bald club.
Instead use the thread pools class
which is an ideal primitive for breaking up lots of work
into little buckets.
See, historically, it was commonplace
that applications would use a dedicated thread model.
That is, one thread that only deals with database rights,
while a separate thread only handles streaming of music,
and a third one only handles networking.
These setups are OK because the amount of work per thread
isn't that large, and it's OK to handle
this work in sequential order.
But there reaches a point where this model starts to fall over.
Say, for example, that you've got 40 bitmaps to decode,
and each decode takes like four milliseconds or something.
Putting all of this work on a single dedicated thread
is a bad idea, since it'll take 80 milliseconds total to get
all that work done in a sequential fashion.
On the other hand, if you created 10 threads
and let each one decode four bitmaps,
then you'd end up only taking 16 milliseconds total.
But then, of course, you run into the problem
of how to properly pass the work around between those threads,
schedule that work, and then managing of those threads.
Before you start stressing out about writing all that code,
don't worry.
This is exactly what ThreadPoolExecuter primitive
is for.
Basically, this class will just let
you spin up a number of threads and toss blocks of work
to execute on it.
ThreadPoolExecuter handles all of the heavy lifting
of spinning up the threads, load balancing
work across those threads, and even killing
those threads when they have been idle for a while.
Basically, it handles all the heavy lifting
of super parallel processing on your behalf.
All you have to do is split up the work.
But there's a small caveat here.
How many threads should your thread pool have?
I mean, technically speaking, you
have the ability to create as many threads as you want.
But that's not ideal.
See, CPUs can only execute a certain number
of threads in parallel.
Once you get above that number, then the CPU
has to start deciding which threads
get the next free block of processor time,
based on how important they are, which
means that if you keep eventually adding threads,
you'll hit a break-even point, where your computation
isn't getting any faster, even though the number
of threads that you have has increased significantly.
And it's also important to note that each of these threads
aren't free.
Each thread costs you about 64k of memory in minimum,
and that adds up quickly, especially
in situations where the call stacks can
start growing pretty large.
As such, your app needs to find a sweet spot
between the number of cores and the point of diminishing return
with the number of threads.
Thankfully, once again, the ThreadPoolExecuter class
has got you covered.
When creating your thread pool, you
can specify the number of initial threads
and the number of maximum threads.
As the workload in the thread pool changes,
it'll scale the number of alive threads to match.
Oh, and a quick note-- the value returned from
get available processors may not reflect
the number of physical cores in the device.
See, some devices have CPUs that will deactivate
one or more cores, depending on the system load,
to save battery.
So if your device has two CPUs, but one of them is asleep,
this value could return one.
And, of course, thread pools won't solve
all of your threading problems.
As mentioned earlier, unless you're
dealing with lots and lots of work packets all the time,
this thing's kind of overkill.
It's best to use things like HandlerThreads or AsyncTask
loaders for specific types of work blocks
and only throw the massive computing
problems at the thread pool.
And for you power users out there,
remember that Renderscript might be a better alternative
to large-scale parallel work on Android devices,
but that's a whole separate set of videos
that we haven't gotten into yet.
And don't forget that Systrace is an amazingly powerful tool
that lets you visualize how work is
flowing through the threads in your application.
It's a great way to validate that things are working
as intended and also see all the other crazy threads that
are being worked on by other parts of your app.
And that's the trick with performance, isn't it?
I mean, you can make assumptions.
But things don't always work the way you think,
which is why you need to check out the rest of the Android
Performance Patterns videos.
And don't forget to join our Google+ community to ask a lot
of hard threading questions as well.
So keep calm, profile your code, and always remember
perf matters.
[MUSIC PLAYING]