Android多线程机制

本文深入探讨Android中多线程的重要性及其实现方式,详细解释Handler机制的工作原理及其在多线程通信中的作用,并介绍不同场景下多线程操作的方法。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

问题

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的MessageQueue
private 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原理?
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值