美文网首页
Android 进程和线程相关知识点整理

Android 进程和线程相关知识点整理

作者: 虞_18bd | 来源:发表于2021-01-05 21:36 被阅读0次

    回想起之前有个面试,一面是问一些项目上的问题,包括金融图表绘制啊,包括一些app应用难点,这些因为都做过,所以很轻松的通过了,但是在二面的时候来了个CTO,上来的第一个问题就是进程和线程的区别
    说实话,在这次面试之前,我对这些基础知识点,算是毫无准备。

    然后我回想起Android有UI线程和子线程,就说了一句,一个进程可以有多个线程。。。

    虽然我之后查阅了不少资料,但是过了这么久,现在只记得:

    进程是资源调度的最小单位

    线程是任务执行的最小单位

    然而在百度里:进程是操作系统资源分配的基本单位,而线程是处理器任务调度和执行的基本单位。还存在资源开销、包含关系、内存分配、影响关系、执行过程等区别。同一进程的线程共享本进程的地址空间和资源,而进程之间的地址空间和资源相互独立。

    =。= 算了我反正是懒得看了,但是在我们日常的工作中,除了一些老哥有过AIDL的经验(这里说到IPC进程间通信,就又出现了一个高频知识点了,待会介绍)之外,Android开发中,多线程主要集中在UI线程(主线程),子线程(异步处理耗时任务)中了。

    刚刚提到了进程间通信就顺带提一下Linux中的跨进程通信

    • 管道 :又分为有名和无名 (无名则才能专心练贱)无名可以让有亲戚关系进程之间通信(父子,爷孙),有名则没有上诉限制,而且都是半双工(发送和接收不能同时进行)
    • 信号量:计数器,用于控制多线程对数据的访问,属于一种同步机制
    • 信号:通知接收进程某个事件已经发生
    • 消息队列:消息链表,存放在内核中,由消息队列标识符标识,UNIX下不同进程之间可实现共享资源的一种机制
    • 共享内存:最快的IPC方式(后面再说原因)
    • Socket:套接字就不用多说了 C/S 模式

    以上是Linux的IPC方式,那Android呢

    首先需要知道,为什么Android App开发要用进程间通信

    几年前我在杭州面试过一家做图片直播的公司,除了一些基本问题,就问到了AIDL,在当时我只知道通过IPC确实可以获取到更多的内存资源,而大部分开发人员也确实是想通过IPC来获取更多的内存上限。

    而其实我们开发中也常常用到IPC,Activity的Intent可以唤起其他应用,如通讯录,电话,短信。。。

    而像广播Broadcast则是可以通知所有程序的IPC,像是电量低等广播

    像是Content Provider则给了数据访问的IPC,可以顺利访问到文件或是数据库 (Binder)

    Messenger:是基于AIDL实现的C/S 通信(不需要处理多线程)

    以上说了这么多,主要核心就两个 AIDL 以及 Binder

    AIDL:如果你要对多个应用进行IPC,并且想在服务里处理多线程,用它就是了

    Binder:Binder是一种进程间通信机制(我是机制=。=)

    • Binder机制有几特点,通过mmap实现了单次数据copy,性能直逼共享内存的方式
    • C/S架构,更符合很多场景(相对于共享内存)
    • 安全性强于传统IPC,因为传统IPC的安全性,是由上层处理的,而Binder通过进程UID/PID可以区分访问的用户到底是谁,而其他传统IPC则是把信息放在请求数据中,那样就有被篡改的风险。

    一不小心说的有点多=。=,回到进程和线程,Android开发中,常用的几个异步线程用法也说一下把:

    最常见的情况就是耗时任务是异步的,但是耗时任务结束之后,需要通知页面进行修改,但是页面的绘制又需要在UI线程上

    • Handler 在Runnable的run方法中发送消息,在Handler中的handleMessage方法接收消息,并完成ui更新(具体原理说明,网上又无数文章)
    • **RxJava **可以通过subscribeOn()和observeOn()在线程间进行切换
    • AsyncTask 本人用的比较少,但是看上去易用性挺强的
    • ThreadPoolExecutor 线程池
    • kotlin协程

    由于篇幅问题,这几种的代码明天将进行说明

    1.首先是Handler的用法

    // Handler就是把UI任务放到handleMessage中执行 hendleMessage则是在sendMessage后会被回调
    
    Handler mHandler = new Handler(){  
        @Override
        public void handleMessage(Message msg) {
            super.handleMessage(msg);
            switch (msg.what){
                case 1:
                    mText.setText("UI操作");
                    break;
                case 2:
                    mText.setText("UI操作2");
                    break;
            }
        }
    };
    
    new Thread(new Runnable() {
        @Override
        public void run() {
            // 耗时操作
            Message msg = new Message();
            msg.what = 1;
            mHandler.sendMessage(msg);
        }
    }).start();
    

    2.RxJava 实现线程切换

    Observable<String> stringOb = Observable.create(new ObservableOnSubscribe<String>() {
        @Override
        public void subscribe(@NonNull ObservableEmitter<String> emitter) throws Throwable {
            //耗时操作
            emitter.onNext("结果");
        }
    });
    
    stringOb.subscribeOn(Schedulers.io())  // 以上发生在子线程
            .observeOn(AndroidSchedulers.mainThread()) // 下面发生在UI线程
            .subscribe(new Consumer<String>() {
                @Override
                public void accept(String s) throws Throwable {
                    // Ui操作
                    System.out.println(s);
                }
            });
    

    3.AsyncTask 实现异步任务

    new MyTask().execute();
    
    class MyTask extends AsyncTask<String, String, String> {
    
         @Override
         protected String doInBackground(String... params) {
            return "耗时任务结果";
         }
    
         @Override
         protected void onPostExecute(String s) {
            // 更新UI
            mText.setText(s);
         }
    }
    

    4.线程池以后会单独说明(根据阿里Android规范手册中看到的,阿里建议是使用线程池而不是其他方式)

    5.kotlin协程

    private suspend fun work(): Long {
        // work work
        return result
    }
    
    launch() {
        var result = withContext(Dispather.IO){
            work()
        } 
    }
    
    launch {
        var deferred = async(Dispather.IO) {//  这里做个同步
            // 耗时操作
            getWebTime()
        }
        var value = deferred.await()// 这里就会等待上面结果 才会继续执行
    }
    

    相关文章

      网友评论

          本文标题:Android 进程和线程相关知识点整理

          本文链接:https://www.haomeiwen.com/subject/hmwwoktx.html