AndroidAndroid 轮子Android Dev

安卓中的线程和线程池

2015-11-03  本文已影响1298人  阿敏其人

本文出自 “阿敏其人” 简书博客,转载或引用请注明出处。

Android沿用了Java的线程模式,其中线程也分主线程和子线程。

一、线程

1、主线程和子线程

一个程序的运行,就是一个进程的在执行,一个进程里面可以拥有很多个线程。

  • 主线程:也叫UI线程,用于运行四大组件和处理他们用户的交互。(主线程就是指进程所拥有的线程,在Java中默认一个进程只有一个线程,那么默认的线程就是我们的主线程)

  • 子线程: 用于执行耗时操作,比如 I/O操作和网络请求等。(安卓3.0以后要求耗访问网络必须在子线程种执行)更新UI的工作必须交给主线程,子线程在安卓里是不允许更新UI的。

2、安卓里,谁是线程

在安卓的世界里面,扮演线程的觉有有如下四个:


二、线程池

1、线程的产生和销毁都会消耗性能

在操作系统中,线程是可以调度的最小单元,线程不能无限制产生,因为创建线程和销毁线程都会有相应的性能开销。

当系统中存在大量的线程的时候,系统会通过时间片轮转的方式调度每个线程,因此在大量线程的情况下没办法让每一个线程都得到绝对的并行,除非线程数量小于或者等于CPU的核心数,一般来说这是不可能的。
所以不可以在一个进程里面大量创建和销毁线程,这是非常消耗性能的行为,所以我们需要使用管理线程,这个管理的工具就叫做—— 线程池

    线程池的基本思想还是一种对象池的思想,开辟一块内存空间,里面存放了众多(未死亡)的线程,池中线程执行调度由池管理器来处理。当有线程任务时,从池中取一个,执行完成后线程对象归池,这样可以避免反复创建线程对象所带来的性能开销,节省了系统的资源。
    比如:一个应用要和网络打交道,有很多步骤需要访问网络,为了不阻塞主线程,每个步骤都创建个线程,在线程中和网络交互,用线程池就变的简单,线程池是对线程的一种封装,让线程用起来更加简便,只需要创一个线程池,把这些步骤像任务一样放进线程池,在程序销毁时只要调用线程池的销毁函数即可。

2、使用线程池的好处

4、Executor 和 ThreadPoolExecutor

安卓中的线程池的概念来源于 Java 中的 Executor。
Executor是一个接口,真正的线程池的实现是 ThreadPoolExecutor 。
ThreadPoolExecutor提供了一系列的参数来配置线程池,通常来说,安卓的线程主要有4种,后面会陆续说到,但是因为Android中的线程池都是直接或者间接通过配置ThreadPoolExecutor来实现的,所以我们这里先了解ThreadPoolExecutor。

5、ThreadPoolExecutor 的构造方法的参数

ThreadPoolExecutor是java.util.concurrent下的一个类,ThreadPoolExecutor有好几个构造方法,我们主要明白了他的构造的方法含义,就大概明白ThreadPoolExecutor是怎么用的了。

    public ThreadPoolExecutor(int corePoolSize,
                              int maximumPoolSize,
                              long keepAliveTime,
                              TimeUnit unit,
                              BlockingQueue<Runnable> workQueue,
                              ThreadFactory threadFactory) {
        this(corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue,
             threadFactory, defaultHandler);
    }
    public ThreadPoolExecutor(int corePoolSize,
                              int maximumPoolSize,
                              long keepAliveTime,
                              TimeUnit unit,
                              BlockingQueue<Runnable> workQueue,
                              ThreadFactory threadFactory,
                              RejectedExecutionHandler handler) {

因为最长,所以我们分析这个最长的

如果将executor的allowCoreThreadTimeOut属性设置为true,那么闲置的核心线程在等待新任务到来时会有超时策略(超时判断),如果在keepAliveTime指定的时间之外还处于等待状态的话,核心线程也会被终止(所以核心线程也不是可以毫无条件地牛逼下去的)


6、线程池的运行机制

一个任务通过 execute(Runnable)方法被添加到线程池,任务就是一个 Runnable类型的对象,任务的执行方法就是 Runnable类型对象的run()方法。

当一个任务通过execute(Runnable)方法欲添加到线程池时:

也就是:处理任务的优先级为:
核心线程corePoolSize、任务队列workQueue、最大线程maximumPoolSize,如果三者都满了,使用handler处理被拒绝的任务。

当线程池中的线程数量大于 corePoolSize时,如果某线程空闲时间超过keepAliveTime,线程将被终止。这样,线程池可以动态的调整池中的线程数。

新任务添加到线程池流程简图

三、线程池的分类

Android中常见的有4中线程池,他们都是直接直接或者间接配置ThreadPoolExecutor来实现自己的功能特性的,他们分别是

这几种线程池的创建都是调用 java.util.concurrent.Executors 里面的方法的。

1、FixedThreadPool

corePoolsize等于maximumPoolSize



newFixedThreadPool 方法在 java.util.concurrent.Executors 里面

84     public static ExecutorService newFixedThreadPool(int nThreads, ThreadFactory threadFactory) {
85         return new ThreadPoolExecutor(nThreads, nThreads,
86                                       0L, TimeUnit.MILLISECONDS,
87                                       new LinkedBlockingQueue<Runnable>(),
88                                       threadFactory);
89     }

查看源码

2、CacheedThreadPool

59     public static ExecutorService newFixedThreadPool(int nThreads) {
60         return new ThreadPoolExecutor(nThreads, nThreads,
61                                       0L, TimeUnit.MILLISECONDS,
62                                       new LinkedBlockingQueue<Runnable>());
63     }

3、ScheduledThreadPool

Creates a thread pool that can schedule commands to run after a given delay, or to execute periodically.
Parameters:
corePoolSize the number of threads to keep in the pool, even if they are idle.
Returns:
a newly created scheduled thread pool
Throws:
java.lang.IllegalArgumentException if corePoolSize < 0
217
218    public static ScheduledExecutorService newScheduledThreadPool(int corePoolSize) {
219        return new ScheduledThreadPoolExecutor(corePoolSize);
220    }

4、SingleThreadExecutor

*特点:
* 线程池内部只有一个核心线程,确保所有任务都在同一个线程中按顺序执行。
* 统一所有的外界任务到同一个线程,任务之间不需要处理线程同步的问题

newSingleThreadExecutor 方法:

Creates an Executor that uses a single worker thread operating off an unbounded queue. (Note however that if this single thread terminates due to a failure during execution prior to shutdown, a new one will take its place if needed to execute subsequent tasks.) Tasks are guaranteed to execute sequentially, and no more than one task will be active at any given time. Unlike the otherwise equivalent newFixedThreadPool(1) the returned executor is guaranteed not to be reconfigurable to use additional threads.
Returns:
the newly created single-threaded Executor
103
104    public static ExecutorService newSingleThreadExecutor() {
105        return new FinalizableDelegatedExecutorService
106            (new ThreadPoolExecutor(1, 1,
107                                    0L, TimeUnit.MILLISECONDS,
108                                    new LinkedBlockingQueue<Runnable>()));
109    }

4种线程池使用简单演示

        ExecutorService fixedThreadPool = Executors.newFixedThreadPool(4);
        fixedThreadPool.execute(command);
        
        ExecutorService cachedThreadPool = Executors.newCachedThreadPool();
        cachedThreadPool.execute(command);
        
        ScheduledExecutorService scheduledThreadPool = Executors.newScheduledThreadPool(4);
        // 2000ms后执行command
        scheduledThreadPool.schedule(command, 2000, TimeUnit.MILLISECONDS);
        // 延迟10ms后,每隔1000ms执行一次command
        scheduledThreadPool.scheduleAtFixedRate(command, 10, 1000, TimeUnit.MILLISECONDS);

        ExecutorService singleThreadExecutor = Executors.newSingleThreadExecutor();
        singleThreadExecutor.execute(command);


参考:
《Android开发艺术探索》
线程池ThreadPoolExecutor使用简介

上一篇下一篇

猜你喜欢

热点阅读