Android多线程机制

来源:互联网 发布:各个国家顶级域名 编辑:程序博客网 时间:2024/05/18 02:26

问题

1)为何需要多线程?
在android中,在主线程中如果耗时太长会出现ANR(android not
Responding),也就是看起来很卡;
一些下载图片,下载数据等耗时操作需要在其他线程执行。
一句话:避免应用太卡,需要使用多线程。


2)多线程如何实现?
多线程实现方式两种方式:
implements Runnable 或 extends Thread


3)多线程机制的核心是啥?
也可以理解为:线程之间的消息传递
一句话:handler机制
3.1 创建一个Handler时一定要关联一个Looper实例,默认构造方法Handler(),它是关联当前Thread的Looper。
我们在UI Thread中创建一个Handler,那么此时就关联了UI Thread的Looper!

public Handler() {    mLooper = Looper.myLooper();}//当前线程的Looper,在Activity创建时,UI线程已经创建了Looper对象//在Handler中机制中Looper是最为核心的,它一直处于循环读MessageQueue,有//要处理的Message就将Message发送给当前的Handler实例来处理

3.2 在创建一个Handler的时候也可以指定Looper,此时的Looper对象,可以是当前线程的也可以是其它线程的!
Handler只是处理它所关联的Looper中的MessageQueue中的Message,至于它哪个线程的Looper,Handler并不是很关心!

我们可以在UI线程中创建一个Handler同时传入Worker的Looper???????

3.3 可Handler到底干了啥呢?简要说明如下:

Activity所在的UI线程在创建的时候,就关联了Looper和MessageQueue,那么我们又在UI线程里创建了自己的Handler,那么Handler是属于UI线程的,从而它是可以和UI线程交互的!UI线程的Looper一直在进行Loop操作MessageQueue读取符合要求的Message给属于它的target即Handler来处理!所 以啊,我们只要在Worker线程中将最新的数据放到Handler所关联的Looper的MessageQueue中,然而Looper一直在loop 操作,一旦有符合要求的Message,就第一时间将Message交给该Message的target即Handler来处理!所以啊,我们在创建 Message的时候就应该指定它的target即Handler

3.4 消息发送有哪几种方法?

但我们也可以,new Message() -- > mHandler.sendMessage(msg) ;这是特例!如果我们通过obtainMessage()方法获取Message对象,此时Handler就会自动设置Message的target。可以看源码!

简单一点说就是:

UI线程或Worker线程提供MessageQueue,Handler向其中填Message,Looper从其中读Message,然后交由 Message自己的target即Handler来处理!!最终被从属于UI线程的Handler的handlMessag(Message msg)方法被调用!!

这就是Android多线程异步处理最为核心的地方!!

3.5 注意点:
(1)在UI线程中创建Handler[一般继承HandleMessage(Message msg)]
(2)Looper可以属于UI线程或Worker线程
(3)从属于Looper的MessgeQueue,Looper一直在loop()操作,在loop()中执行msg.target.dispatchMessage(msg);调用Handler的handleMessage(Message msg)

在创建一个Looper时,就创建了从属于该Looper的MessageQueueprivate Looper() {mQueue = new MessageQueue();mRun = true;mThread = Thread.currentThread();}

(4)在 Worker线程中获取Message,然后通过Handler传入MessageQueue
(5)handler处理消息。


4)到底有多少种实现方式?

4.1 在异步线程操作UI控件

利用handler

handler.sendMessage(message)-----------handleMessage方法回调

4.2 控件自己本身操作

textview.post(Runnable action)textview.postDelay(Runnable action , long miliseconds)

4.3 activity的调用方法
runOnUiThread(Runnable action)

public final void runOnUiThread(Runnable action) {if (Thread.currentThread() != mUiThread) {//如果当前线程不是UI线程mHandler.post(action);} else {action.run();}}其中:mUiThread = Thread.currentThread() ;mHandler = new Handler()

4.4 AsyncTask(在UI线程中、只能实例化一次的)

onPreExecute() --在UI线程中执行,作一些初始化操作doInBackground(Params... params) --在Worker线程中执行,进行耗时的后台处理,在该方法中可以调用publishProgress(Progress progress) 进行进度处理onProgressUpdate(Progress progress) --在UI线程中执行,进行进度实时处理onPostExecute(Result result) --在UI线程中执行, 在doInBackground(Params ... params)返回后调用onCancelled() --在UI线程中执行,在AsyncTask实例调用cancle(true)方法后执行,作一些清理操作

注意点

AsyncTask必须在UI线程中创建,asyncTask.execute(Params... params) ;在UI线程中执行,且只能执行一次要想再次调用execute(Params... params),必须重新创建AsyncTask对象

遗留问题

  1. handler从消息队列轮询处理消息,当消息处理完了会怎样?
  2. AsyncTask优缺点有哪些?
    优点是解决了多线程处理问题
    缺点是每处理一个任务需要一个新的实例来执行
  3. 当同一时间有很多耗时操作时,需要new thread很多实例,任务执行完成后,会被虚拟机垃圾回收gc,降低程序性能。
    原理:当频繁创建销毁某个类型的对象实例时,会产生很多临时对象,当失去引用的临时对象较多时,就会gc。
    如何自定义线程池来处理这一个问题?
  4. 我们可以在UI线程中创建一个Handler同时传入Worker的Looper,那么handler处理消息是来自UI线程还是worker线程,还是两个都处理?
  5. 用一张图来阐述handler原理?
原创粉丝点击