[背景音乐]
[MUSIC]
啊 线程
Ah, threading.
强大到可以用来折叠DNA
So powerful that you canfold genomes with it,
但也难用到让普通程序员发疯
but so difficultthat it can drive the average programmer insane.
我叫科尔特·麦克安利斯
My name is Colt McAnlis, and as far
在Android开发中 线程是
as Android development is concerned, threading is one
所有要应对的事物里
of the most important and most confusing
最重要也是最让人困惑的
things that you can deal with,
这意味着 要想写出尽可能快的应用
which means if you want to write the fastest app possible,
你需要花时间理解
you’ve gotta take a minute andunderstand the subtle art that
多线程编程的微妙之处
is multithreaded programming.
在Android系统提供的大量函数中
Remember that in the vastworld of Android functions
很多操作只能在主线程上执行
there’s a whole boatload ofoperations that only execute
例如 系统事件 输入事件
on the main thread–system events, input events,
应用回调 服务 甚至定时器
application callbackservices, and even alarms.
大多数情况下 你写的代码
And for the most part,any code that you write
都是在这些操作内执行 这意味着
executes inside one of theseoperations, which means it also
你写的代码会运行在主线程上
runs on the main thread. Now,
如果你记得的话 在主线程上执行的代码
if you recall, work thatexecutes on the main thread
是从一个工作队列的头部
gets there after being pulled from the front
取出来的
of a work queue,
所以任务是按照顺序执行
so blocks of workare done in order,
这一个任务执行完了才轮到下一个任务
and the next block ofwork isn’t processed until the current
one is completed,
这意味着 如果某个大任务
which means if there is a large chunk
在输入事件
of work between an input
和它的回调中间执行
event and its callback,
用户等待结果的时间会超出他的预期
then the user will have to wait longer than expected to see results.
别忘了
And don’t forget
大部分的屏幕渲染也在主线程里执行
that the main thread is also where most of the screen rendering occurs.
当动画或屏幕刷新时
While an animation orscreen update is occurring,
系统会每隔16毫秒重新绘制屏幕
the system will try todraw the screen every 16
以达到每秒60帧这个流畅的刷新率
milliseconds or so to achievesmooth 60 frames per second.
问题是主线程同时在响应
The problem is that this is happening
屏幕刷新与输入事件
while the thread is also responding to app input events.
如果你的应用在动画之间
So if your app is
执行了某些耗时超过预期的代码
in the middle of an animation and some random work packet takes longer than expected,
就会错过在这个16毫秒窗口内
you’ll miss your chanceto render that next frame
渲染下一帧的机会 这一帧就被推迟了
within the 16millisecond window, and that frame will be delayed.
这就叫做丢帧
This is what we call a dropped frame,
丢帧只要发生
and when this happens,
用户就会注意到
users start to notice.
直接解决的方法就是
The direct solution here is to
把任何可能延迟16毫秒刷新窗口期的代码
move anything that might upset the 16 millisecond window
移动到其他地方 比如另一个线程
over somewhere else, liketo a different thread.
这样的话其他任务就不会
This way it won’t be contesting
和UI线程竞争资源
with the UI thread for work
也就不会打断
to be done, andwon’t be interrupting
屏幕绘制
the drawing of the screen,
这就是在Android上使用多线程
which is the whole point of threading
全部要点的简单概括
on Android in a nutshell.
那么现在的问题是将这个任务转移的
So the question at hand,what’s the best way
最佳方式是什么
to offload this work,
以及该转移什么类型的任务
and how do you choose what types of work
幸好
to offload? Thankfully,
Android框架提供了很多类
the Android framework has provided a handful
可以辅助你完成这件事
of classes to help make this a bit easier for you.
比如AsyncTask类
For example, theAsyncTask class is
它适合将任务在UI线程内外转移
ideal for helping you getwork on and off the UI thread the right way.
HandlerThreads则更适合让用特定线程来处理回调
HandlerThreads are great when you need a dedicated thread for callbacks to land on.
ThreadPool适用于你将任务拆解到
ThreadPools work best whenyou can break your work up
非常小的碎片来执行
into really small packets,
使用一系列线程来处理 而IntentServices
and then toss them to a bunch of threads, and IntentServices
更适用于执行后台任务
are really ideal forbackground tasks,
或者在UI线程外响应intent任务
or when you need to get intent work off the UI thread.
和其他所有问题一样 没有银弹
And like everything else, thereis not a silver bullet here,
但是 知道哪种情况用哪个类很重要
but knowing whichprimitive is best
可以避免很多让人头疼的情况
for what situation can saveyou a lot of headaches.
但请注意 这些花哨的辅助类都
But note that having allthose fancy helper classes
无法规避一个大问题 内存
doesn’t hide thebig problem, memory. See,
因为 内存和多线程从来不能完美配合
threading and memoryhave never really played well,
Android平台也是一样
and on the Androidplatform it’s no different.
例如 你在一个activity里面
For example, if you declareone of those fancy threading
声明了这个线程
primitives insideof an activity,
这个类就会隐式引用外部activity
it now contains animplicit reference
这可能会导致在activity销毁时
to the outer activity,which can cause a memory
内存泄漏 因为线程里的任务还在执行
leak if the activity is destroyed, but the threaded work is still alive. Or,
想想用户在旋转了屏幕后 如果某个
what happens when theuser rotates the device,
创建了很多线程的activity被销毁会怎样
destroying anactivity that spawned a bunch of threaded work?
这意味着 这些碎片任务
I mean, chances arethat those work packets
会引用着多个UI对象
would have referencesback to various UI objects
但其实这些对象已经不复存在了
that don’t really exist anymore.
事实上 Android平台充斥着大量线程
And the truth is that the Android platform is flooded with threads.
如果你想了解下 可以用systrace抓取一下
If you need a reminder ofthat, grab a Systrace capture
看看背后发生了哪些很酷的
and check out all the cool stuff that’s going
但你不曾了解的事情
on underneath the hood that you never really knew about.
好啦 总结下 多线程对于
See, at the end of the day, threading
确保Android应用 拥有高性能 十分重要
is critical to ensure high performance of your android app,
但是还有很多其他问题
but there’s lots of other problems
你同样需要考虑
that you have to worryabout that as well, which
这也是你需要看看
is why you should check out the rest
Android性能课程其他部分的原因
of the Android Performance Patterns videos.
别忘了加入我们的Google+社区
And also, don’t forget to joinour Google+ community so that
遇到麻烦的时候可以提问
you can ask questions whenyou run into problems.
心平气和地profile你的代码吧
So keep calm, profile yourcode
请一定记住 性能很重要
and always remember, perf matters
[背景音乐]
[MUSIC]
