从一场面试说起-Android多线程入门(4)

前言

话说为什么要写bolg呢,最近面试的时候,总是会遇到一些奇奇怪怪的问题,之前有的时候遇到过,但是没有深入了解,还有的就完全不懂,也算是一个查漏补缺的过程。最重要的一点就是对自我的认可,在工作中我总是感觉缺乏对自己的认可,觉得自己这也不行那也不行,很多东西只知其一但是不知其二,说是科班出身都感觉有点丢人,操作系统,计组之类的本来是同源同根,但是因为没有吃透搞得好像分离一样。写blog一方面积累自己,另一方面也是分享一下学习的过程,共勉

主要还是说Android中的多线程,上个bolg写了synchronized的一些基本用法,今天应该写lock的用法来着,先缓缓,过一两天在写。根据之前的Android中的多线程通信,打算写一下runOnUiThread。

正文

首先看下什么是runOnUiThread。

/**
     * Runs the specified action on the UI thread. If the current thread is the UI
     * thread, then the action is executed immediately. If the current thread is
     * not the UI thread, the action is posted to the event queue of the UI thread.
     *
     * @param action the action to run on the UI thread
     */

翻译一下

在UI线程执行指定的操作。如果当前线程是UI线程,那么立即执行相应的操作;如果当前线程不是UI线程,那么就把这个操作放到UI线程的事件队列里面。

从官方的说明里,我感觉有几个可以想的问题点

1. 什么是UI Thread

2. 这个Event Queue指的是什么

带着这两个问题,来看下源码

UIThread

public final void runOnUiThread(Runnable action) {
        if (Thread.currentThread() != mUiThread) {
            mHandler.post(action);
        } else {
            action.run();
        }
    }

runOnUiThread在Activity中的final方法(突然感觉final也很重要,之后要写写)。

这里我们要传入一个Runnable对象,然后判断当前的线程,首先判断当前线程是否是UI线程,如果不是,调用mHandler.post方法,否则就使用action.run()方法。看起来很简单粗暴,之前也分析过Handler.post(),这里不做解释了。

private Thread mUiThread;

简简单单,这个mUiThred是一个线程(这不是废话嘛),但是我想看看它是怎么初始化的。


    final void attach(Context context, ActivityThread aThread,
            Instrumentation instr, IBinder token, int ident,
            Application application, Intent intent, ActivityInfo info,
            CharSequence title, Activity parent, String id,
            NonConfigurationInstances lastNonConfigurationInstances,
            Configuration config, String referrer, IVoiceInteractor voiceInteractor,
            Window window, ActivityConfigCallback activityConfigCallback, IBinder assistToken) {
        attachBaseContext(context);
        //...
        mUiThread = Thread.currentThread();
        //...
    }

这个方法其实还是比较大的,这个mUiThred就是操作attch的线程来初始化的,但是这个又是谁干的呢?ui线程和主线程的区别在哪里?

这个时候必须要搞清楚是谁调用了attach方法,涉及到activity的初始化已经应用的初始化。整个流程涉及到进程间通信,Binder机制,涉及到Activity中的许多涉及模式,之后有机会再深入学习。

我们都知道我们的Activity是通过ActivityThread进行启动的,通过AMS进行调度,所以在ActivityThread中寻找相关的痕迹,在performLaunchActivity中发现了attach的调用

 private Activity performLaunchActivity(ActivityClientRecord r, Intent customIntent) {
    //code
        activity.attach(appContext, this, getInstrumentation(), r.token,
                        r.ident, app, r.intent, r.activityInfo, title, r.parent,
                        r.embeddedID, r.lastNonConfigurationInstances, config,
                        r.referrer, r.voiceInteractor, window, r.configCallback,
                        r.assistToken);
   //code
    }

在这里发现传入的第二个参数是this,也就是我们的ActivityThread的实例。同时该方法也是被ActivityThread所调用,所以得到结论

不管是之前提到的mUiThred或者mMainThread,指的是同一个线程,也就是我们的ActivityThread线程。这下问题1的结果就有了,接下来看下问题2EventQueue

EventQueue

由于之前分析过Handler,知道Handler其实是和MessageQueue还有Looper一些协作达到异步消息处理的效果,这个MessageQueue是就是我们的EventQueue,在MessageQueue中使用一个链表按照时间顺序把接收到的Message插入到相应的位置,这里的EventQueue指的就是这个MessageQueue。

结束

这一节内容比较少,但是有关于应用启动的流程,包括跟AMS,WMS的交互显得格外重要,FWK层的东西必须要深入了解才能体会到其精髓。之后也会写单独的bolg来分析这块内容。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值