这个是 Android 特有的概念。线程间的通信方式:eventbus、rxjava、livedata。然而,这些方式的底层原理都是基于 handler,所以,下面我将为大家讲解 handler 通信原理。
handler调度流程:
子线程: handler.sendMessage(msg) =》 handler.enqueueMessage =》MessageQueue.enqueueMessage()
主线程:Looper.loop=》queue.next()=》handler.handleMessage()
handler的核心原理图:
两个重要类的图解:
JVM 垃圾回收机制:GCroot 回收机制
持有链: static sThreadLocal -》 mLooper -》MessageQueue -》msg -》handler -》 activity
解决方法:打破持有链
new Thread( () -> { Handler mHandler = new Handler(new Handler.Callback() { @Override public boolean handleMessage(@NonNull Message msg) { return false; } }); mHandler.sendMessage(new Message()); } ).start();
报错展示:
Process: com.wust.empty02, PID: 25002 java.lang.RuntimeException: Can't create handler inside thread Thread[Thread-2,5,main] that has not called Looper.prepare() at android.os.Handler.<init>(Handler.java:207) at android.os.Handler.<init>(Handler.java:133) at com.wust.empty02.MainActivity.lambda$onCreate$0$MainActivity(MainActivity.java:20) at com.wust.empty02.MainActivity$$ExternalSyntheticLambda0.run(Unknown Source:2) at java.lang.Thread.run(Thread.java:919)
报错源码位置:
new Thread( () -> { //创建该线程的 looper Looper.prepare(); //创建该线程的 handler Handler mHandler = new Handler(new Handler.Callback() { @Override public boolean handleMessage(@NonNull Message msg) { return false; } }); //looper开启循环 Looper.loop(); } ).start();
这种写法有一个缺点:这样的话 该线程就只能创建一个handler。
package com.wust.empty02; import android.os.Bundle; import android.os.Handler; import android.os.Looper; import androidx.appcompat.app.AppCompatActivity; public class MainActivity extends AppCompatActivity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); MyHandlerThread t = new MyHandlerThread(); t.start(); try { //这句话如果去掉 就会导致 t.getmLooper() 为空,因为你无法保证 Handler handler = new Handler(t.getmLooper()); 在 t 线程 run 之后执行 Thread.sleep(1000*3); } catch (InterruptedException e) { e.printStackTrace(); } Handler handler = new Handler(t.getmLooper()); } } class MyHandlerThread extends Thread { private Looper mLooper; @Override public void run() { Looper.prepare(); this.mLooper = Looper.myLooper(); Looper.loop(); } public Looper getmLooper() { return mLooper; } }
从上面代码的注释 就可以很明显的看出其缺点之所在了。无法保证 t.getmLooper() 在 线程 run 方法之后执行。
HandlerThread t = new HandlerThread("wustyq"); t.start(); Handler handler = new Handler(t.getLooper());
系统的这个 HandlerThread 中的 run 方法为什么就能保证在 t.getLooper() 之前执行呢??关键代码 + 关键思想如下:
为什么要用 synchronized ? 为了解决并发操作 =》 即 run 和 getLooper 只能同时执行一个。
为什么要用 notifyAll() ?因为有可能多个线程调用了wait()方法进行等待。
为什么要用 while?不用 if?因为这个 wait() 可能由别的线程 notify() 唤醒。所以要使用while反复检测。
quit:loop退出。防止内存泄漏。不会被停止。
会调用底层 Linux =》 epoll 完成等待
obtain()