Android

ThreadPoolExecutor配置细节

2019-03-24  本文已影响31人  12313凯皇

Android中,线程池的概念来源于Java,主要是通过Executor来派生特定类型的线程池,不同种类的线程池又各有各的特性。Executor是一个接口,而真正的线程池的实现为ThreadPoolExecutor,它的构造方法提供了一系列参数来配置线程池,下面是ThreadPoolExecutor的一个较常用的构造方法:

public ThreadPoolExecutor(int corePoolSize,
                          int maximumPoolSize,
                          long keepAliveTime,
                          TimeUnit unit,
                          BlockingQueue<Runnable> workQueue,
                          ThreadFactory threadFactory) {
    this(corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue,
            threadFactory, defaultHandler);
}

首先我们来介绍一下构造方法中几个参数的含义:

除了上面的这些主要参数以外,ThreadPoolExecutor还有一个不常用的参数RejectedExecutionHandler handler。当线程池无法执行新任务时,这可能是由于任务队列已满或者是无法成功执行任务,这个时候ThreadPoolExecutor会调用handlerrejectedExecution方法来通知调用者,默认情况下rejectedExecution方法会直接抛出一个RejectedExecutionExceptionThreadPoolExecutorRejectedExecutionHandler提供了几个可选值:CallerRunsPolicyAbortPolicyDiscardPolicyDiscardOldestPolicy,其中AbortPolicy是默认值,它会直接抛出RejectedExecutionException

ThreadPoolExecutor执行任务时大致遵循如下规则

  1. 如果线程池中的线程数量未达到核心线程的数量,那么会直接启动一个核心线程来执行任务。
  2. 如果线程池中的线程数量已经达到或者超过核心线程的数量,那么任务会被插入到任务队列中排队等候执行。
  3. 如果在步骤2中无法将任务插入到任务队列中,这往往是由于任务队列已满,这个时候如果线程数量未达到线程池规定的最大值,那么会立刻启动一个非核心线程来执行任务。
  4. 如果步骤3中线程数量已经达到线程池规定的最大值,那么就拒绝执行此任务,ThreadPoolExecutor会调用RejectedExecutionHandlerrejectedExecution方法来通知调用者。

ThreadPoolExecutor的参数配置在AsyncTask中有明显的体现,下面是AsyncTask中的线程池的配置情况:

private static final int CPU_COUNT = Runtime.getRuntime().availableProcessors();
// We want at least 2 threads and at most 4 threads in the core pool,
// preferring to have 1 less than the CPU count to avoid saturating
// the CPU with background work
private static final int CORE_POOL_SIZE = Math.max(2, Math.min(CPU_COUNT - 1, 4));
private static final int MAXIMUM_POOL_SIZE = CPU_COUNT * 2 + 1;
private static final int KEEP_ALIVE_SECONDS = 30;

private static final ThreadFactory sThreadFactory = new ThreadFactory() {
    private final AtomicInteger mCount = new AtomicInteger(1);

    public Thread newThread(Runnable r) {
        return new Thread(r, "AsyncTask #" + mCount.getAndIncrement());
    }
};

private static final BlockingQueue<Runnable> sPoolWorkQueue =
        new LinkedBlockingQueue<Runnable>(128);

/**
 * An {@link Executor} that can be used to execute tasks in parallel.
 */
public static final Executor THREAD_POOL_EXECUTOR;

static {
    ThreadPoolExecutor threadPoolExecutor = new ThreadPoolExecutor(
            CORE_POOL_SIZE, MAXIMUM_POOL_SIZE, KEEP_ALIVE_SECONDS, TimeUnit.SECONDS,
            sPoolWorkQueue, sThreadFactory);
    threadPoolExecutor.allowCoreThreadTimeOut(true);
    THREAD_POOL_EXECUTOR = threadPoolExecutor;
}

通过上面的代码我们可以知道,AsyncTaskTHREAD_POOL_EXECUTOR这个线程池进行了配置,配置后的线程池规格如下:

:上述源码版本为API26,不同版本源码会有些许差别,但大致配置过程是相同的。

上一篇下一篇

猜你喜欢

热点阅读