Android 中线程池的理解

来源:互联网 发布:空气质量实时监测数据 编辑:程序博客网 时间:2024/05/21 19:32

Android 中线程池的理解

前言

Android的日常开发中会用到线程池的地方也不少见,Android中的线程池也是沿用了Java的Executor的方式。关于这些资料网上能搜罗出一大把。现在突然看了一下源码,感觉灵光一闪呀。在这里把自己的理解记录下来。

以前来说,对于线程池的使用只知道有4中,分别为:FixedThreadPoolCachedThreadPoolScheduledThreadPoolSingleThreadExecutor,然而不知道其中的原理。后来翻了一下源码,发现这4中线程池的具体实现都是通过一个方法来实现的:

/** * Creates a new {@code ThreadPoolExecutor} with the given initial * parameters and default thread factory and rejected execution handler. * It may be more convenient to use one of the {@link Executors} factory * methods instead of this general purpose constructor. * * @param corePoolSize the number of threads to keep in the pool, even *        if they are idle, unless {@code allowCoreThreadTimeOut} is set * @param maximumPoolSize the maximum number of threads to allow in the *        pool * @param keepAliveTime when the number of threads is greater than *        the core, this is the maximum time that excess idle threads *        will wait for new tasks before terminating. * @param unit the time unit for the {@code keepAliveTime} argument * @param workQueue the queue to use for holding tasks before they are *        executed.  This queue will hold only the {@code Runnable} *        tasks submitted by the {@code execute} method. * @throws IllegalArgumentException if one of the following holds:<br> *         {@code corePoolSize < 0}<br> *         {@code keepAliveTime < 0}<br> *         {@code maximumPoolSize <= 0}<br> *         {@code maximumPoolSize < corePoolSize} * @throws NullPointerException if {@code workQueue} is null */public ThreadPoolExecutor(int corePoolSize,                                int maximunPoolSize,                                long keepAliveTime,                                TimeUnit unit,                                BlockingQueue<Runnable> workQueue,                                ThreadFactory threadFactory)
  • corePoolSize:根据上面注释的解释,这个参数代表核心线程数,这些线程是在线程池保存,即使在闲置的状态下也不会销毁的。除非调用了allowCoreThreadTimeOut(true)方法。

  • maximunPoolSize:这个参数代表的是线程池中最大的线程数,包括和核心线程和普通线程。当活动线程数量达到这个数值后,后续任务会被阻塞

  • keepAliveTime:普通线程在限制状态下的超时时间,超过这个时间之后,线程就会被终止。当allowCoreThreadTimeOut(true)被调用后,这个参数对核心线程也生效

  • unit:这个参数代表keepAliveTime的单位,通常有TimeUnit.MILLSECONDS(毫秒)、TimeUnit.SECONDS(秒)、TimeUnit.MINUTES(分钟)等。

  • workQueue:用来保存那些还没有执行的Runnable对象的队列,只有使用execute方法的对象才会保存在这个队列中。当线程池中的线程数量大于核心线程数的时候,会把线程保存在这里。如果线程池的线程数量没有达到最大值,就开启新的普通线程来执行这些任务。如果这个队列保存的任务数达到了上限,而且没有空闲线程的话,则拒绝执行任务。

  • threadFactory:线程工厂,为线程池提供创建新的线程功能。

JAVA中为我们提供了几个具体的线程池实现类:

FixedThreadPool

通过Executors.newFixedThreadPool()来创建

public static ExecutorService newFixedThreadPool(int nThreads) {    return new ThreadPoolExecutor(nThreads, nThreads,                                  0L, TimeUnit.MILLISECONDS,                                  new LinkedBlockingQueue<Runnable>());

}

FixedThreadPool的实现得知,该线程池具有固定的线程数量,当线程处于空闲状态下,都不会被回收,除非线程池关闭了,当线程池的所有线程都在活动状态的时候,新任务会保存在队列中,并且new LinkedBlockingQueue<Runnable>()这个队列是没有大小限制的。由于线程不会被回收,所以这种线程池能够快速的响应任务。

CachedThreadPool

通过Executors.newCachedThreadPool()创建。

public static ExecutorService newCachedThreadPool() {    return new ThreadPoolExecutor(0, Integer.MAX_VALUE,                                  60L, TimeUnit.SECONDS,                                  new SynchronousQueue<Runnable>());}

可以看到,这个线程池没有核心线程,但是线程数量最大值为Integer.MAX_VALUE,这意味着能线程池的线程数量差不多可以无限大,当一个新任务来到的时候,就检验是否有闲置的线程,如果有就直接执行,没有就创建一个来执行。闲置线程的超时时间为60秒。超过60秒之后就会被回收。

关于SynchronousQueue上网查询了一下资料,这个对象是一个只有一个元素的队列,只有队列当请求取出的时候才能插入,内部并没有数据缓存空间。我们可以简单理解为这个其实没什么乱用的东西,在这里的场景中只是实现了任务能被马上执行。

通过以上特点,我觉得这个线程池适合用于大量耗时短的任务,并且因为当没有任务的时候,线程池是空的,所以系统资源占用比较少。

ScheduledThreadPool

通过Executors.newScheduledThreadPool()创建

public static ScheduledExecutorService newScheduledThreadPool(int corePoolSize) {    return new ScheduledThreadPoolExecutor(corePoolSize);}public ScheduledThreadPoolExecutor(int corePoolSize) {     super(corePoolSize, Integer.MAX_VALUE,      DEFAULT_KEEPALIVE_MILLIS, MILLISECONDS,          new DelayedWorkQueue());}

其中 DEFAULT_KEEPALIVE_MILLIS 的值为10L,意味着10毫秒就会回收闲置线程,这个线程池的最大线程数量也没有限制,主要的适用场景可能为定时任务或者固定周期性任务。

SingleThreadExecutor

通过Executors.newSingleThreadExecutor方法来创建。

public static ExecutorService newSingleThreadExecutor(ThreadFactory threadFactory) {    return new FinalizableDelegatedExecutorService        (new ThreadPoolExecutor(1, 1,                                0L, TimeUnit.MILLISECONDS,                                new LinkedBlockingQueue<Runnable>(),                                threadFactory));}

这个线程池的内部只有一个核心线程,所有的任务都在同一个线程按顺序执行,这些线程就不需要处理线程之间同步的问题了,看具体的适用场景了。

0 0
原创粉丝点击