Handler不是直接用来实现线程切换的, 而是用于在A线程调用B线程的实例,去处理消息或执行Runnable对象。间接完成切换。
Handler从线程A切换到线程B的底层原理
0. 线程切换的实现
- 实际的线程切换: 首先清楚:Handler是与创建它的线程的Looper绑定的,而不是与调用它的线程的Looper绑定。 在线程A中,通过调用线程B的Handler实例来发送消息(sendMessage)或执行Runnable任务(post)。 这些消息或任务被添加到线程B的MessageQueue中等待以及后续处理。
1. 准备工作
- 线程B的准备:在线程B中,首先需要调用
Looper.prepare()方法来为该线程初始化Looper和MessageQueue。这一步是必需的,因为Looper和MessageQueue是处理消息和执行Runnable的基础设施。 - Handler的创建:在线程B中创建Handler实例,这个Handler会与线程B的Looper和MessageQueue绑定。
class ThreadB extends Thread {
private Handler handler;
@Override
public void run() {
Looper.prepare(); // 初始化Looper
handler = new Handler() {
@Override
public void handleMessage(Message msg) {
// 在这里处理来自线程A的消息
super.handleMessage(msg);
// 例如,更新UI(但通常UI更新应在主线程进行,这里仅为示例)
Log.d("ThreadB", "Handling message in ThreadB");
}
};
Looper.loop(); // 启动Looper循环
}
// 提供Handler的访问方式
public Handler getHandler() {
return handler;
}
}
2. 消息发送
- 从线程A发送消息:在线程A中,通过线程B的Handler实例来发送消息(Message)或执行Runnable对象。
这可以通过调用Handler的
sendMessage(Message msg)或post(Runnable r)等方法来实现。
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
// 启动线程B
ThreadB threadB = new ThreadB();
threadB.start();
// 发送消息到线程B
Message msg = Message.obtain();
// 假设threadBHandler是线程B的Handler实例
// threadBHandler.sendMessage(msg); // 这里我们省略了直接获取handler的步骤
// 由于直接获取handler的示例在真实场景中不常见,我们改用Runnable来演示
Runnable runnable = new Runnable() {
@Override
public void run() {
// 这里是将在线程B中执行的代码
Log.d("Runnable", "Running in ThreadB");
}
};
// 假设我们有一个方法来获取Handler(这里我们直接调用,但实际上你需要从ThreadB中获取)
// Handler threadBHandler = getThreadBHandlerSomehow();
// threadBHandler.post(runnable);
// 在实际应用中,你需要在ThreadB完全启动并Handler可用后,才能发送消息或Runnable
}
// 注意:这里并没有真正的方法getThreadBHandlerSomehow(),你需要自己实现同步机制来获取Handler
}
3. 消息处理
- 线程B的消息循环:
在线程B中,Looper的
loop()方法会不断地从MessageQueue中取出消息并分发给相应的Handler进行处理。 由于线程B的Handler与线程B的Looper和MessageQueue绑定,因此当线程A发送的消息被取出时,它会在线程B中被处理。
注意事项
- Handler的线程绑定:Handler是与创建它的线程的Looper绑定的,而不是与调用它的线程的Looper绑定。因此,要确保从正确的线程中获取Handler实例。
- 线程间的通信:Handler机制实际上是一种线程间的通信方式,它允许我们在一个线程中发送消息或任务,并在另一个线程中接收并处理这些消息或任务。
- 内存泄漏:在使用Handler时,要注意避免内存泄漏的问题。特别是在非主线程中创建的Handler,如果其持有的引用(如Activity的引用)没有在适当的时候被清除,就可能导致内存泄漏。
通过上述原理,我们可以理解Handler是如何间接地实现线程切换的。然而,需要明确的是,Handler本身并不直接负责线程的切换,而是通过与Looper和MessageQueue的协作,在目标线程中处理来自其他线程的消息或任务。