Android thread

 本片文章将介绍android的线程相关知识,主要分为二个部分:背景知识、线程种类以及各自的适用场景,文章摘自efficient android threading

一、背景知识

      图1

如上图所示:从上往下是三个大的层次:应用层、ART层(android run time)、Linux 层。每创建一个应用,都会经过如下步骤:

1、开启一个linux 进程

2、创建runtime 虚拟机

3、创建application 实例

4   创建启动这个应用的入口组件(如activity、service)

进程设置了优先级,这样os才能决定在资源不足时应该舍弃谁,android的优先级设定结合了android的基本组件

Foreground 

application 有一个可见的组件在前台,有一个绑定到service的activity运行在前台的另一个进程中,有broadcast在运行

Visiable

application 有一个部分可见的组件

Service

service在后台运行,未绑定到前台activity中

Background

一个不可见的activity

Empty

没有活跃的组件

 

     每一个应用外面都包裹着art虚拟机、Linux 进程,运行在Linux os中,进程设置了优先级,方便os对进程进行资源的调度和管理,为了提高用户体验,进程内部开辟了特殊的ui线程,也就是main线程来更新ui,其他耗时操作都应该重新开辟线程

     线程都是从进程中创建的,而且,所有的线程都是linux thread。线程跟进程很想,唯一的差别就是能不能共享资源。linux os层面关心的更多的是线程,而不是进程,不管外在的应用有什么样的形式,在底层就是线程的执行,linux 依赖什么来调度线程呢,线程之间的竞争又是依靠什么,有两个因素:

1、 priority:改变线程的优先级

2、control group:改变android指定的cgroup

priority:基本上线程创建时,就会从创建它的线程集成它的优先级, 如下图所示。uithread创建的工作线程有着和自己一样的default优先级,反过来还会和自己竞争资源,我们一定要手动设定工作线程的优先级,一般是        Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND);   

 

private void init(ThreadGroup g, Runnable target, String name, long stackSize) {
    Thread parent = currentThread();
    if (g == null) {
        g = parent.getThreadGroup();
    }

    g.addUnstarted();
    this.group = g;

    this.target = target;
    this.priority = parent.getPriority();
    this.daemon = parent.isDaemon();
    setName(name);

    init2(parent);

    /* Stash the specified stack size in case the VM cares */
    this.stackSize = stackSize;
    tid = nextThreadID();
}

 

 control group:cgroup 主要是方便管理线程,将一组线程放在一起,统一分配一样的执行时间,在android中重要的是两种类型的cgroup:Foreground Group和 Background Group

 

二者和进程等级对应关系如下:

 

cgroup

process rank

fg

foreground

fg

visibale

bg

service

bg

background

bg

empty

 二者竞争分配的cpu执行时间如下:

                                                                                 图2
如果进程在前台,那么它创建的线程都属于fg,会获取更多执行时间,如果按home键,应用切换到后台,那么原来属于fg的线程会变成属于bg。另外,前面我们说的主动降低线程的优先级,也会将此线程放置到bg,尽管有时它创建于前台进程。

 

二、线程种类

1、handlerthread

       最大特点就是执行任务的顺序性,另外就是handler的特点容易使用和复用,sendmessage即可,任务容易组成任务链,通过handler的message.what串联起来,任务之间通过handler传递data方便

2、executor

       最大特点就是复用线程,通过生产者消费者模型,并发执行多个任务,可以和service结合,能够被多个组件共享调用,生命周期也独立于调用组件,通过intent调用,可跨进程

内部执行:

  1、如果线程个数小于核心,则开启线程执行

  2、如果能够放进阻塞队列,则放入,否则,3

  3、是否超过最大线程数,未超过,则创建,否则4

  4、拒绝

3、intentservice

       内部其实是个handlerthread,但是由于是service组件包装,所以提高了优先级,而且独立于启动它的组件的生命周期,handlerthread的适用场景同样也适用于intentservice,有一个特殊场景需要注意,broadcast 的onreceive执行在主线程,当有耗时操作时,需要开启线程,但是onreceive执行完,则broadcast组件生命周期结束,如果这是进程的入口,那么进程会变为一个空进程,很容易被杀死,这时候intentservice就是个很好的选择。

如果任务的执行受控制于客户侧,或者需要并发执行,则建议适用service 内部建立多线程调度的方式

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值