💎一站式轻松地调用各大LLM模型接口,支持GPT4、智谱、星火、月之暗面及文生图 广告
[TOC] # Handler原理分析 ## 关键流程 1、Looper不断的从MessageQueue中取出Message,然后交给Message对应的Handler处理。同时Handler还执行发送Message到MessageQueue中的动作。 2、Handler对象持有Looper的目的是为了拿到Looper对应的MessageQueue,并往其中插入消息;Looper从MessageQueue中取出Message后,交给Message的target也就是Handler对象处理。 3、Looper对象存储在ThreadLocal中,属于线程局部变量,只能被当前线程访问。 ## 详细介绍 1、Handler调用sendMessage、post方法发送Message,并插入到MessageQueue中,MessaQueue采用单链表结构。 2、Handler类有一个Looper成员变量,Looper属于线程局部变量,每个线程有且只能有一个Looper;Looper类有一个MessageQueue成员变量;Handler持有Looper主要是为了拿到Looper对应的MessageQueue,并往其中插入消息。 3、子线程需要先调用Looper.prepare方法,来创建一个Looper对象存储到ThreadLocal中。然后创建Handler时会调用Looper.myLooper方法获取当前线程的Looper。 4、Looper.loop方法开启消息循环,Looper会循环从其MessageQueue中提取消息,并调用消息的target(也就是Handler)进行分发处理 5、Handler拿到Message后,先判断Message的Callback是否为空,不为空直接执行,消息处理结束;为空则判断Handler的Callback是否为空,不为空则执行,并决定是否进行拦截,拦截则消息处理结束;不拦截则执行Handler的handleMessage方法。 ## ThreadLocal介绍 1、ThreadLocal是一个创建线程局部变量的类。 2、一般情况下,我们创建的线程可以被任何一个线程访问并修改,而使用ThreadLocal创建的变量只能被当前线程访问,其他线程无法访问和修改。 3、ThreadLocal的set方法存入的值,实际是放到当前线程的ThreadLocalMap实例中,key是当前ThreadLocal对象,value是存入的值。 4、get方法直接从当前线程的ThreadLocalMap中,根据key获取对象 # 一个线程中初始化多个Handler,会产生多少个Looper 只会产生一个Looper。因为Looper是和当前线程进行绑定的,属于线程局部变量,每个线程有且只能有一个Looper # 如果只有一个Looper,Looper如何区分Handler,Handler发送了消息会不会导致Looper错乱,最终不知道谁处理 Handler在将消息插入到消息队列时,会将消息的target属性设置为该Handler自身,消息的target属性为空时是无法插入消息队列的。Looper取出消息后会调用该消息的target属性(也就是Handler对象)的dispatchMessage方法来分发消息给相应的Handler。 # 多进程和多线程的区别 1、本质区别在于:每个进程拥有自己的一整套变量,而线程则共享数据。 2、进程是程序的一次执行。计算机在同一刻运行多个程序,每个程序称为一个进程(计算机将 CPU 的时间片分配给每一个进程) 3、线程是 CPU 的基本调度单位。一个程序同时执行多个任务,每个任务称为一个线程 # 进程间通讯方法,线程间通讯方法 1、进程间通讯方法: * Broadcast * Intent/Bundle * File 共享 * Messenger * AIDL * ContentProvider * Socket 2、线程间通讯方法: * Handler(AsyncTask、Message、runOnUiThread 等) * EventBus * LocalBroadcast # 关键字 synchronized 的作用 # sleep 和 wait 的区别 1、二者都可以暂停当前线程,释放 CPU 控制权 2、区别在于作用于谁和是否释放锁? 3、wait 方法作用于 Object,sleep 方法作用于 Thread Object.wait 方法在释放 CPU 的同时,释放了对象锁的控制,使得其他线程可以使用同步控制块或方法;Thread.sleep 方法没有释放锁