牛骨文教育服务平台(让学习变的简单)

其实在我眼里,线程池是一个很高端的东西,它会管理很多线程,并在进程中进行多线程的操作,是一个很高效且方便使用的东西。本篇文章就说说我对线程池的认识。

一,线程池的基本概念

线程池有很多优点,比如避免了重复创建和销毁线程而降低了程序的运行效率,其次它可以很方便的控制线程的最大并发数,在一定程度上可以减少线程间的阻塞等。在android中线程池是由java的Executor实现的。它的真正实现类是ThreadPoolExecutor,下面是它的构造方法和相关介绍。

ThreadPoolExecutor(int corePoolSize,int maximumPoolSize,long keepAliveTime,TimeUnit unit,BlockingQueueworkQueue,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的源码解析,里面就运用了线程池。