一个线程有几个handler?

答:作为应用层的类时,一个线程允许同时存在多个handler,但是都属于一个Looper; hander作为通信机制时,仅有一套统信机制looper,安卓与主线程通信的跨线程通信底层都是通过looper;

一个线程对应一个Looper,一个Looper一个MessageQueue;

线程间统信的原理是怎样的?

image-20230423105219078

image-20230423105246678

handler发送msg流程:handler.sendMessage()->handler.enquenueMessage->MessageQueue.enqueueMessage;

主线程取消息/处理消息流程:Activity,main()->Looper.loop()->MessageQueue.next()->handler.dispatchMessage->handler.hanleMessage();

线程间的通信原理是内存共享(MessageQueue共享);

Handler内存泄漏的原因?为什么其他内部类没有过这种问题?

1
2
3
4
5
6
7
8
//MainActivity.class
private Handler mHandler=new Handler(){
@Override
public void handleMessage(@NonNull Message msg) {
super.handleMessage(msg);
click(); //调用这个方法时默认为MainActivity.this.click();会持有MainActivity.this的对象;
}
}

handler在activity中使用时的持有链: statuc sThreadLocal->Looper->MessageQueue Message->Handler-MainActivity.this;

当handler执行delay消息时,jvm无法回收上面的持有链,导致内存泄漏;

1
2
3
解决方案:
1.handler加static关键字,然后外部方法才有弱引用,软引用;
2.activity销毁时释放所有handler的消息,如 mHandler.removeCallbacksAndMessages(null);

子线程多并发安全的使用handler:

1
2
3
4
HandlerThread handlerThread = new HandlerThread("threadName");
handlerThread.start();//HandlerThread中处理了looper同步和线程锁等问题;
Handler handler1 = new Handler(handlerThread.getLooper());
Handler handler2 = new Handler(handlerThread.getLooper());

message消息复用:

1
mHandler.obtainMessage();//清空消息后复用message对象,大量new Message会存在内存抖动;