Android 线程池的使用

来源:互联网 发布:青岛seo外包公司费用 编辑:程序博客网 时间:2024/06/07 06:54

1. 为什么Android开发需要线程池

第一:降低资源消耗。通过重复利用已创建的线程降低线程创建和销毁造成的 消耗。
第二:提高响应速度。当任务到达时,任务可以不需要等到线程创建就能立即执 行。
第三:提高线程的可管理性。线程是稀缺资源,如果无限制的创建,不仅会消耗系统资源,还会降低系统的稳定性,使用线程池可以进行统一的分配,调优和监控

2. Executor Executors ThreadPoolExecutor ScheduledThreadPoolExecutor

  1. Executor 是一个接口,提供了一个名为 void execute(Runnable command); 的方法。
  2. Executors 提供了一些创建线程池的工具方法。
  3. ScheduledThreadPoolExecutor 类来支持周期性任务的调度。它是可调度的线程池
  4. 接口ExecutorService 表述了异步执行的机制,并且可以让任务在后台执行。ExecutorService 实例因此特别像线程池。事实上,在 java.util.concurrent 包中的ExecutorService 的实现就是线程池的实现。(后面详解)
  5. ThreadPoolExecutor 它就是管理线程的线程池了,这个是它其中一个构造方法.
public ThreadPoolExecutor(int corePoolSize,                              int maximumPoolSize,                              long keepAliveTime,                              TimeUnit unit,                              BlockingQueue<Runnable> workQueue,                              RejectedExecutionHandler handler) {        this(corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue,             Executors.defaultThreadFactory(), handler);    }

参数的含义:
1. corePoolSize: 核心线程数,会一直存活,即使没有任务,线程池也会维护线程的最少数量
2. maximumPoolSize: 线程池维护线程的最大数量
3. keepAliveTime TimeUnit: keepAliveTime参数和timeUnit参数也是配合使用的,keepAliveTime参数指明等待时间的量化值,timeUnit指明量化值单位。例如keepAliveTime=1,timeUnit为TimeUnit.MINUTES,代表空闲线程的回收阀值为1分钟
4. workQueue: 线程池所使用的缓冲队列,常用的是:java.util.concurrent.ArrayBlockingQueue、LinkedBlockingQueue、SynchronousQueue
5. handler: 线程池中的数量大于maximumPoolSize,对拒绝任务的处理策略,默认值ThreadPoolExecutor.AbortPolicy()。

3.线程池的工作过程

  1. 首先可以通过线程池提供的submit()方法或者execute()方法,要求线程池执行某个任务。线程池收到这个要求执行的任务后,会有几种处理情况:
    • 如果当前线程池中运行的线程数量还没有达到corePoolSize大小时,线程池会创建一个新的线程运行你的任务,无论之前已经创建的线程是否处于空闲状态。
    • 如果当前线程池中运行的线程数量已经达到设置的corePoolSize大小,线程池会把你的这个任务加入到等待队列中。直到某一个的线程空闲了,线程池会根据设置的等待队列规则,从队列中取出一个新的任务执行。
    • 如果根据队列规则,这个任务无法加入等待队列。这时线程池就会创建一个“非核心线程”直接运行这个任务。注意,如果这种情况下任务执行成功,那么当前线程池中的线程数量一定大于corePoolSize。
    • 如果这个任务,无法被“核心线程”直接执行,又无法加入等待队列,又无法创建“非核心线程”直接执行,且你没有为线程池设置RejectedExecutionHandler。这时线程池会抛出RejectedExecutionException异常,即线程池拒绝接受这个任务。
  2. 一旦线程池中某个线程完成了任务的执行,它就会试图到任务等待队列中拿去下一个等待任务(所有的等待任务都实现了BlockingQueue接口,按照接口字面上的理解,这是一个可阻塞的队列接口),它会调用等待队列的poll()方法,并停留在哪里。
  3. 当线程池中的线程超过你设置的corePoolSize参数,说明当前线程池中有所谓的“非核心线程”。那么当某个线程处理完任务后,如果等待keepAliveTime时间后仍然没有新的任务分配给它,那么这个线程将会被回收。线程池回收线程时,对所谓的“核心线程”和“非核心线程”是一视同仁的,直到线程池中线程的数量等于你设置的corePoolSize参数时,回收过程才会停止。

4. 如何使用线程池

  1. newCachedThreadPool创建一个可缓存的线程池。如果线程池的大小超过了处理任务所需要的线程,那么就会回收部分空闲(60秒不执行任务)的线程,当任务数增加时,此线程池又可以智能的添加新线程来处理任务。此线程池不会对线程池大小做限制,线程池大小完全依赖于操作系统(或者说JVM)能够创建的最大线程大小
 ExecutorService service= Executors.newCachedThreadPool();
  1. SingleThreadExecutor 创建一个单线程的线程池。这个线程池只有一个线程在工作,也就是相当于单线程串行执行所有任务。如果这个唯一的线程因为异常结束,那么会有一个新的线程来替代它。此线程池保证所有任务的执行顺序按照任务的提交顺序执行。
ExecutorServiceservice=Executors.newSingleThreadExecutor();
  1. newFixedThreadPool创建固定大小的线程池。每次提交一个任务就创建一个线程,直到线程达到线程池的最大大小。线程池的大小一旦达到最大值就会保持不变,如果某个线程因为执行异常而结束,那么线程池会补充一个新线程。
  ExecutorService service= Executors.newFixedThreadPool(0);
  1. newScheduledThreadPool创建一个大小无限的线程池。此线程池支持定时以及周期性执行任务的需求
  ExecutorService service= Executors.newScheduledThreadPool(0);
原创粉丝点击