19. 线程池

Android 中的线程池就是 java 中的线程池,即 ThreadPoolExecutor 类。

Java 通过 Executors 提供四种线程池:

  1. newCachedThreadPool

    创建一个可缓存的线程池

  2. newFixedThreadPool

    创建一个定长线程池,可控制线程最大并发数,超出的线程会在队列中等待。

  3. newScheduledThreadPool

    创建一个定长线程池,支持定时及周期性任务执行。

  4. newSingleThreadExecutor

    创建一个单线程化的线程池,它只会用唯一的工作线程来执行任务,保证所有任务按照指定顺序(FIFO, LIFO, 优先级)执行。

Executors 是一个线程池的工具类,上面四个方法最终都是调用的 ThreadPoolExecutor。理解 ThreadPoolExecutor 就可以完全理解线程池。

线程池解决了 2 个问题:

  1. 当执行大量异步任务时,通过减少每个任务的调用开销来提高性能。
  2. 提供了限制管理线程资源的方法。

ThreadPoolExecutor

public class ThreadPoolExecutor extends AbstractExecutorService 

构造

    /**
     *
     * @param corePoolSize  保持在线程池中的线程数,即使线程处于空闲状态,除非设置了 allowCoreThreadTimeOut
     * @param maximumPoolSize 线程最大数量
     * @param keepAliveTime 线程数大于 corePoolSize 时,线程池中的空闲线程等待新任务执行的最大时间,超过这个时间,空闲线程就会被终止。
     * @param unit keepAliveTime 的时间单位
     * @param workQueue 任务队列
     * @param threadFactory 线程工厂
     * @param handler 线程被阻塞时的处理者,因为到达了线程的最大数量或者任务队列满了。
     */
    public ThreadPoolExecutor(int corePoolSize,
                              int maximumPoolSize,
                              long keepAliveTime,
                              TimeUnit unit,
                              BlockingQueue workQueue,
                              ThreadFactory threadFactory,
                              RejectedExecutionHandler handler) {
        
        // 检查参数
        if (corePoolSize < 0 ||
                maximumPoolSize <= 0 ||
                maximumPoolSize < corePoolSize ||
                keepAliveTime < 0)
            throw new IllegalArgumentException();
        if (workQueue == null || threadFactory == null || handler == null)
            throw new NullPointerException();
        
        // 赋值
        this.corePoolSize = corePoolSize;
        this.maximumPoolSize = maximumPoolSize;
        this.workQueue = workQueue;
        this.keepAliveTime = unit.toNanos(keepAliveTime);
        this.threadFactory = threadFactory;
        this.handler = handler;
    }

执行流程

执行流程可以用这张图来概括:


image

通过 execute()方法执行线程池,内部会自动根据我们构造参数的信息分配处理 Runnable。

    public void execute(Runnable command) {
        // Runnable 不可以为空
        if (command == null)
            throw new NullPointerException();
        
        // ctl 是一个 AtomicInteger,用来记录正在运行的线程数量
        int c = ctl.get();
        // 当前核心的线程数量

参考

深入理解Java之线程池

Android 开发艺术探索 11.3

你可能感兴趣的:(19. 线程池)