🔥码云GVP开源项目 12k star Uniapp+ElementUI 功能强大 支持多语言、二开方便! 广告
其实在我眼里,线程池是一个很高端的东西,它会管理很多线程,并在进程中进行多线程的操作,是一个很高效且方便使用的东西。本篇文章就说说我对线程池的认识。 ### 一,线程池的基本概念 线程池有很多优点,比如避免了重复创建和销毁线程而降低了程序的运行效率,其次它可以很方便的控制线程的最大并发数,在一定程度上可以减少线程间的阻塞等。在android中线程池是由java的Executor实现的。它的真正实现类是ThreadPoolExecutor,下面是它的构造方法和相关介绍。 ThreadPoolExecutor(int corePoolSize,int maximumPoolSize,long keepAliveTime,TimeUnit unit,BlockingQueue<Runnalbe>workQueue,ThreadFactory threadFactory) **corePoolSize:**核心线程数量,它会一直存在,没任务就处理闲置状态 。如果allowCoreThreadTimeOut设置为true,则闲置的核心线程会有超时策略,时间由keepAliveTime控制,当超时时,核心线程就会被终止。 **maximumPoolSize:**线程池能容纳的最大线程数,当活动数达到这个数时,后续的新任务将会被阻塞。 **keepAliveTime:**超时时非核心线程会被回收,如果allowCoreThreadTimeOut设置为true,核心线程也会被回收。 **unit:**指定keepAliveTime的单位。TimeUnit.MILLISECONDS(毫秒),TimeUnit.SECONDS(秒)等。 **workQueue:**线程中的任务队列,通过线程池的excute方法提交的Runnable会存储到这参数中。 **threadFactory:**线程工厂,为线程池提供创建新线程的功能。 了解了上面的概念后,我们来看下android线程池的分类。 ### 二,线程池的分类 1.FixedThreadPool 这是一种线程数量固定的线程池。处理空闲状态时,并不会被回收,除非线程池关闭。它的源码如下: ~~~ public static ExecutorService newFixedThreadPool(int nThreads) { return new ThreadPoolExecutor(nThreads, nThreads, 0L, TimeUnit.MILLISECONDS, new LinkedBlockingQueue<Runnable>()); } ~~~ 由上面介绍的ThreadPoolExecutor可知,FixedThreadPool的核心线程有nThreads条,最大线程也相同,这证明了它没有非核心线程,且FixedThreadPool没有超时策略,所以空闲时线程不会被回收。此外它的任务队列也是无限大的。它适合用于需要快速响应的外界请求的情况下。接下来看下它的用法。 ~~~ ExecutorService fixedThreadPool = Executors.newFixedThreadPool(4); fixedThreadPool.execute(Runnable); ~~~ 用法很简单,只需要使用Executors就可创建FixedThreadPool,并初始化线程数。看到这个,以后开线程就不需要再用Thread了。 2.CacheThreadPool 是一种线程数量不定的线程池,只有非核心线程,并且最大线程数可以说是无穷大。当线程池中的线程都处于活动状态时,创建新线程。这类线程适合执行大量耗时较少的任务。看下它的构造方法: ~~~ <pre name="code" class="java"><pre name="code" class="java"> public static final int MAX_VALUE = 0x7FFFFFFF; ~~~ ~~~ public static ExecutorService newCachedThreadPool() { return new ThreadPoolExecutor(0, Integer.MAX_VALUE, 60L, TimeUnit.SECONDS, new SynchronousQueue<Runnable>()); } ~~~ 同样很好理解,没有核心线程,最大线程娄是MAX_VALUE,基本可以理解成无上限,超时机制是60秒,由上分析可知,它在闲置60秒后会被回收,所以基本不占系统资源。看下它的用法。 ~~~ ExecutorService cachedThreadPool = Executors.newCachedThreadPool(); cachedThreadPool.execute(runnable); ~~~ 3.scheduledThreadPool 核心线程数量是固定的,而非核心线程数是没有限制的,并且非核心线程闲置时会被立即回收,可用于执行定时和具有固定周期的重复任务。看下它的构造方法: ~~~ public ScheduledThreadPoolExecutor(int corePoolSize) { super(corePoolSize, Integer.MAX_VALUE, 0, NANOSECONDS, new DelayedWorkQueue()); } ~~~ super就相当于调用了ThreadPoolExecutor,看下它的用法: ~~~ ScheduledExecutorService scheduledThreadPool = Executors.newScheduledThreadPool(4); // 1s后执行command scheduledThreadPool.schedule(runnable, 1000, TimeUnit.MILLISECONDS); // 延迟10ms后,每隔1000ms执行一次command scheduledThreadPool.scheduleAtFixedRate(runnable, 10, 1000, TimeUnit.MILLISECONDS); ~~~ 4.SingleThreadExecutor 内部只有一个线程,确保任务都在一个线程中按顺序执行。这个多用于串行处理情况。不用考虑并发的问题。它的构造方法如下: ~~~ public static ExecutorService newSingleThreadExecutor(ThreadFactory threadFactory) { return new FinalizableDelegatedExecutorService (new ThreadPoolExecutor(1, 1, 0L, TimeUnit.MILLISECONDS, new LinkedBlockingQueue<Runnable>(), threadFactory)); } ~~~ 没什么好解释的,来看下它的用法: ~~~ ExecutorService singleThreadExecutor = Executors.newSingleThreadExecutor(); singleThreadExecutor.execute(runnable);</span> ~~~ 分析完所有线程池后,我们得知,不同线程池有不同的应用环境,并没有说哪个比较好。在实际情况中我们要根据自己的需求来适当的选择。其实线程池在android的源码中有大量的使用,下一篇博客将讲解下AsyncTask的源码解析,里面就运用了线程池。