[coolxing按: 转载请注明作者和出处, 如有谬误, 欢迎在评论中指正.]
多线程在所有编程语言中都是比较难以理解和掌握的, 这几天上网看了很多android多线程方面的资料, 在这里做一些总结.
什么时候使用多线程:
1. 耗时操作使用多线程, 耗时操作放在UI线程中会导致用户的操作无法得到响应.
2. 阻塞操作使用多线程, 理由同上.
3. 多核CUP的设备使用多线程, 可以有效提高CPU的利用率.
4. 并行操作使用多线程.
android中的多线程模型主要涉及的类有:Looper, Handler, MessageQueue, Message等.
Looper类用来创建消息队列. 每个线程最多只能有一个消息队列, android中UI线程默认具有消息队列, 但非UI线程在默认情况下是不具备消息队列的. 如果需要在非UI线程中开启消息队列, 需要调用Looper.prepare()方法, 在该方法的执行过程中会创建一个Looper对象, 而Looper的构造函数中会创建一个MessageQueue instance(Looper的构造函数是私有的, 在Looper类之外无法创建其对象). 此后再为该线程绑定一个Handler instance, 然后调用Looper.loop()方法, 就可以不断的从消息队列中取出消息和处理消息了. Looper.myLoop()方法可以得到线程的Looper对象, 如果为null, 说明此时该线程尚未开启消息队列.
Handler类用于处理消息. 该类具有四个构造函数:
1. public Handler(). 创建好的Handler instance将绑定在代码所在的线程的消息队列上, 因此一定要确定该线程开启了消息队列, 否则程序将发生错误. 使用这个构造函数创建Handler instance, 一般来说, 我们需要重写Hanler类的handleMessage()方法, 以便在之后的消息处理时调用.
2. public Handler(Callback callback). Callback是Handler内部定义的一个接口, 因此想要使用这个构造函数创建Handler对象, 需要自定义一个类实现Callback接口, 并重写接口中定义的handleMessage()方法. 这个构造函数其实与无参的构造函数类似, 也要确保代码所在的线程开启了消息队列. 不同的是在之后处理消息时, 将调用callback的handleMessage()方法, 而不是Handler对象的handleMssage()方法.
3. public Handler(Looper looper). 这个构造函数表示创建一个Handler instance, 并将其绑定在looper所在的线程上. 此时looper不能为null. 此时一般也需要重写Hanler类的handleMessage()方法
4. public Handler(Looper looper, Callback callback). 可以结合2和3理解.
MessageQueue类用于表示消息队列. 队列中的每一个Message都有一个when字段, 这个字段用来决定Message应该何时出对处理. 消息队列中的每一个Message根据when字段的大小由小到大排列, 排在最前面的消息会首先得到处理, 因此可以说消息队列并不是一个严格的先进先出的队列.
Message类用于表示消息. Message对象可以通过arg1, arg2, obj字段和setData()携带数据, 此外还具有很多字段. when字段决定Message应该何时出对处理, target字段用来表示将由哪个Handler对象处理这个消息, next字段表示在消息队列中排在这个Message之后的下一个Message, callback字段如果不为null表示这个Message包装了一个runnable对象, what字段表示code, 即这个消息具体是什么类型的消息. 每个what都在其handler的namespace中, 我们只需要确保将由同一个handler处理的消息的what属性不重复就可以.
将消息压入消息队列: Message对象的target字段关联了哪个线程的消息队列, 这个消息就会被压入哪个线程的消息队列中.
1. 调用Handler类中以send开头的方法可以将Message对象压入消息队列中, 调用Handler类中以post开头的方法可以将一个runnable对象包装在一个Message对象中, 然后再压入消息队列, 此时入队的Message其callback字段不为null, 值就是这个runnable对象. 调用Handler对象的这些方法入队的Message, 其target属性会被赋值为这个handler对象.
2. 调用Message对象的sendToTarget()方法可以将其本身压入与其target字段(即handler对象)所关联的消息队列中.
将未来得及处理的消息从消息队列中删除:
调用Handler对象中以remove开头的方法就可以.
从消息队列中取出消息并处理消息: 所有在消息队列中的消息, 都具有target字段. 消息是在target所关联的线程上被取出和处理的.
1. 如果取出的Message对象的callback字段不为null, 那么就调用callback字段的run()方法(callback字段的类型是runnable). 注意此时并不开启一个新的线程运行run()方法, 而是直接在handler对象(即Message的target字段)所关联的线程上运行.
2. 如果取出的Message对象的callback字段为null, 且Handler对象中的callback字段也为null, 那么这个消息将由Handler对象的handleMessage(msg)方法处理. 注意Message对象的callback字段是Runnable类型的而Handler对象的callback字段是Callback类型的, Handler对象的callback字段是在创建Handler instance的时候指定的, 如果没有指定则这个字段为null, 详见Handler类的四个构造方法.
3. 如果取出的Message对象的callback字段为null, 且Handler对象中的callback字段不为null, 那么这个消息将由Handler对象中的callback字段的handleMessage方法处理.
线程间通信: 有了以上的叙述, 线程间的通信也就好理解了. 假如一个handler关联了A线程上的消息队列, 那么我们可以在B线程上调用handler的相关方法向A线程上的消息队列压入一个Message, 这个Message将在A线程上得到处理.
android中还有一些和多线程有关的类, 比如AsyncTask, HandlerThread等, 这些以后再总结.
分享到:
相关推荐
创建Handler时,通常会关联到一个Looper,这个Looper负责从MessageQueue中取出消息并分发给对应的Handler。 接着,我们来看看Looper。Looper是消息循环的管理者,它会在一个线程中不断运行,等待MessageQueue中的...
Looper的主要职责是从MessageQueue中取出Message,然后交由对应的Handler的`handleMessage()`方法进行处理。处理完成后,会调用Message的`recycle()`方法将其放入MessagePool中以便下次使用。 ##### 4、Handler:...
Looper 是一个类,它负责在一个线程中创建消息循环,不断从 MessageQueue 中取出消息并分发给关联的 Handler。每个线程默认并不包含 Looper,需要手动调用 `Looper.prepare()` 初始化,然后调用 `Looper.loop()` ...
Handler获取当前线程中的looper对象,looper用来从存放Message的MessageQueue中取出Message,再有Handler进行Message的分发和处理. 简单定义: 1、Message Queue(消息队列): 用来存放通过Handler发布的消息,通常...
Looper会从MessageQueue中取出下一个消息并交给Handler处理。MessageQueue通过addMessage()方法将新消息添加到队列,然后Looper通过pollNext()或next()方法获取队列中的下一个消息。 MessagePool是Message对象的...
Looper是消息循环器,它负责从Message Queue中取出Message并分发给对应的Handler。在Android系统中,主线程默认已经有一个运行的Looper,但如果我们需要在自定义线程中使用Handler进行消息通信,就需要手动创建并...
- **消息处理**:Looper会不断地从MessageQueue中取出消息,并交给相应的Handler处理。 ##### 3. Handler Handler是用于发送消息和处理消息的关键类。每个Handler实例都与一个特定的线程及其消息队列关联。 - **...
Android 多线程 Looper Handler Android 操作系统中,多线程是一种常见的编程技术,通过使用多线程,可以提高应用程序的响应速度和效率。在 Android 中,多线程可以分为两种:有消息循环的线程和没有消息循环的线程...
在主线程即UI线程外,新建一个Looper线程,并用Messenger和Handler来处理message和posted runnable。程序中,在负线程中默认加了一个3s的线程等来,来帮助理解sent message和post runnable之间的同步机制。所以在按...
Looper.prepare()方法初始化MessageQueue,而Looper.loop()则进入一个无限循环,不断从MessageQueue中取出消息并传递给对应的Handler进行处理。 MessageQueue(消息队列)是一个FIFO(先进先出)的数据结构,存储待...
- Looper是管理线程内部消息交换的核心类,负责调度Message Queue中的消息。 - 每个线程可以有一个Looper,用于维护Message Queue,并按顺序处理消息。 - Looper对象不仅存放消息,还负责将消息分发给对应的...
- **Handler的使用**:Handler对象可以用来与Looper交互,向Message Queue中推送消息,或者接收Looper从队列中取出的消息。 - **线程间的通信**:线程A的Handler引用可以传递给其他线程B或C,使得它们可以向线程A...
4. **Looper循环**:Looper不断地从MessageQueue中取出Message并交给对应的Handler处理。 5. **处理消息**:Handler通过重写`handleMessage()`方法来处理消息。 #### 五、示例代码解析 为了更好地理解上述概念,...
Looper是消息循环的载体,它负责从MessageQueue中取出Message并分发给对应的Handler。每个线程都有自己的消息队列,但默认情况下,只有Android的主线程(UI线程)拥有一个Looper。如果要在其他线程中使用Handler,就...
MessageQueue 是线程对应 Looper 的一部分,负责存储从后台进程中抛回的和当前 Handler 绑定的 Message,是一个队列。 Looper 是什么?Looper 相当于一个 MessageQueue 的管理人员,它会不停的循环的遍历队列,然后...
`Handler`有四个构造函数,其中默认的构造函数将`Handler`与当前线程的`Looper`和`MessageQueue`关联。用户通常需要重写`handleMessage`方法来处理接收到的消息。`Callback`接口提供了另一种处理消息的方式,用户...
总的来说,`Handler`、`Looper`和`Message`是Android多线程编程中的重要工具,它们通过消息机制,帮助开发者有效地管理线程间的通信,实现异步处理,提升应用的性能和用户体验。理解这三个组件的工作原理和使用方式...
【Looper】:Looper是线程中的消息循环器,负责从MessageQueue中取出Message并交给相应的Handler进行处理。Looper通过`loop()`方法执行一个无限循环,不断检查MessageQueue是否有新消息。主线程的Looper会持续运行,...
Looper会从Message Queue中取出消息并分发给对应的Handler进行处理。 4. **Looper** Looper是循环器,它持续不断地从Message Queue中取出消息并交给Handler处理。主线程默认有一个Looper,而其他线程需要手动调用`...
在 Android 中,每个线程都有一个 Looper 对象,该对象负责将 MessageQueue 中的消息 dispatch 到对应的 Handler 中。Looper 的初始状态是空闲的,当有消息到达时,Looper 会将其 dispatch 到对应的 Handler 中,并...