Android中HandlerThread子类重写的run()方法为何无法完整执行?
HandlerThread重写run()看不到结束日志的原因及解决办法
问题根源
你遇到的问题来自两个关键错误:
1. 错误给重写的run()方法添加synchronized修饰符
原HandlerThread的run()方法并没有synchronized修饰,你添加这个关键字后会导致:
run()方法执行期间会一直持有当前HandlerThreadTest对象的锁- 当主线程调用
quitSafely()时,该方法内部会调用getLooper(),而getLooper()包含synchronized (this)同步块,需要获取当前对象的锁 - 此时
HandlerThread的run()卡在Looper.loop()循环,锁被持续持有,主线程的getLooper()会被永久阻塞,quitSafely()无法触发Looper退出,super.run()永远无法返回,自然看不到"Looper end!"日志
2. Handler初始化时机错误
在HandlerThreadTest的构造方法中创建mHandler时,HandlerThread还未启动,此时Handler默认绑定主线程的Looper,而非HandlerThread自身的Looper。这导致你post的Runnable实际在主线程执行,逻辑不符合预期。
修复方案
步骤1:移除run()的synchronized修饰符
恢复run()方法的原有修饰,避免锁阻塞:
@Override public void run() { Log.d(Tag, "Looper start!"); super.run(); Log.d(Tag, "Looper end!"); }
步骤2:正确初始化Handler
在onLooperPrepared()方法中初始化mHandler,此时HandlerThread的Looper已创建完成,确保Handler绑定当前线程的Looper:
static class HandlerThreadTest extends android.os.HandlerThread { private Handler mHandler; public HandlerThreadTest(String name) { super(name); } public HandlerThreadTest(String name, int priority) { super(name, priority); } @Override protected void onLooperPrepared() { super.onLooperPrepared(); // 此时Looper已初始化,绑定当前线程的Looper mHandler = new Handler(getLooper()); } public Handler getHandler() { return mHandler; } @Override public void run() { Log.d(Tag, "Looper start!"); super.run(); Log.d(Tag, "Looper end!"); } }
步骤3:确保HandlerThread启动后再使用
调用test_ThreadHandler前必须先启动线程:
HandlerThreadTest threadTest = new HandlerThreadTest("MyHandlerThread"); threadTest.start(); test_ThreadHandler(threadTest);
验证效果
修复后执行流程:
HandlerThreadTest.start()启动线程,执行run()打印"Looper start!"super.run()创建Looper并进入循环,onLooperPrepared()初始化绑定当前线程Looper的mHandlerpost的Runnable被发送到HandlerThread的消息队列,在该线程执行,打印"handlerThreadTest quit!"并调用quitSafely()- Looper处理完现有消息后退出循环,
super.run()返回,打印"Looper end!" HandlerThread线程正常结束
内容的提问来源于stack exchange,提问作者Jack_Du
相关产品推荐
相关产品推荐

