本文主要是介绍Android 中线程池的理解,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!
Android 中线程池的理解
前言
在Android
的日常开发中会用到线程池的地方也不少见,Android
中的线程池也是沿用了Java的Executor的方式。关于这些资料网上能搜罗出一大把。现在突然看了一下源码,感觉灵光一闪呀。在这里把自己的理解记录下来。
以前来说,对于线程池的使用只知道有4中,分别为:FixedThreadPool
、CachedThreadPool
、ScheduledThreadPool
、SingleThreadExecutor
,然而不知道其中的原理。后来翻了一下源码,发现这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));
}
这个线程池的内部只有一个核心线程,所有的任务都在同一个线程按顺序执行,这些线程就不需要处理线程之间同步的问题了,看具体的适用场景了。
这篇关于Android 中线程池的理解的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!