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

回想起之前有个面试,一面是问一些项目上的问题,包括金融图表绘制啊,包括一些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 stringOb = Observable.create(new ObservableOnSubscribe() {
    @Override
    public void subscribe(@NonNull ObservableEmitter emitter) throws Throwable {
        //耗时操作
        emitter.onNext("结果");
    }
});

stringOb.subscribeOn(Schedulers.io())  // 以上发生在子线程
        .observeOn(AndroidSchedulers.mainThread()) // 下面发生在UI线程
        .subscribe(new Consumer() {
            @Override
            public void accept(String s) throws Throwable {
                // Ui操作
                System.out.println(s);
            }
        });

3.AsyncTask 实现异步任务

new MyTask().execute();

class MyTask extends AsyncTask {

     @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 进程和线程相关知识点整理)