• Android ThreadPoolExecutor线程池


    引言

    Android的线程池概念来自于Java的Executor,真正的线程池实现为ThreadPoolExecutor。在Android中,提供了4类不同的线程池,具体下面会说到。为什么使用线程池呢?而不是使用Thread创建线程呢?因为使用线程池有以下几个优点:

    • 重用线程池的线程,避免因为线程的创建和销毁所带来的性能开销
    • 能有效控制线程池的最大并发数,避免线程之间抢占资源导致阻塞
    • 能够对线程进行简单的管理,并提供定时执行以及指定间隔循环执行等功能

    所以需要多次创建Thread时使用线程池较好。

    ThreadPoolExecutor

    它是线程池的真正实现,构造函数提供一系列的参数配置线程池。

    public ThreadPoolExecutor(int corePoolSize,
                              int maximumPoolSize,
                              long keepAliveTime,
                              TimeUnit unit,
                              BlockingQueue<Runnable> workQueue,
                              ThreadFactory threadFactory,
                              RejectedExecutionHandler handler)
    
    • corePoolSize:核心线程数,默认情况下,即时处于闲置状态下,核心线程会在线程一直存活;如果设置allowCoreThreadTimeOut为true,闲置的核心线程等待任务期间会有超时策略,时间间隔由keepAliveTime设置,最大为CPU核心数+1
    • maximumPoolSize:线程池容纳最大线程数,当活动线程数超过这个数值,后续的新任务会导致阻塞,最大为CPU核心数2倍+1
    • keepAliveTime:非核心线程闲置时超时的时长,如果设置allowCoreThreadTimeOut为true,即作用于闲置的核心线程
    • unit:时间单位,使用TimeUnit枚举
    • workQueue:线程池中的任务队列,通过线程池execute方法提交Runnable对象会存储这个参数中,容量为128
    • threadFactory:线程工厂,为线程池提供创建新线程的功能
    • handler:线程池对拒绝任务的处理策略。一般是队列已满或者无法成功执行任务,这时ThreadPoolExecutor会调用handler的rejectedExecution方法来通知调用者,有四个策略:
      • ThreadPoolExecutor.AbortPolicy() 直接抛出异常RejectedExecutionException
      • ThreadPoolExecutor.CallerRunsPolicy() 直接调用run方法并且阻塞执行
      • ThreadPoolExecutor.DiscardPolicy() 直接丢弃后来的任务
      • ThreadPoolExecutor.DiscardOldestPolicy() 丢弃在队列中队首的任务

    执行任务规则可用currentSize表示线程池中当前线程数量,将上述过程可以表示如下

    • 当currentSize < corePoolSize时,直接启动一个核心线程并执行任务
    • 当currentSize>=corePoolSize、并且workQueue未满时,添加进来的任务会被安排到workQueue中等待执行
    • 当workQueue已满,但是currentSize<maximumPoolSize时,会立即开启一个非核心线程来执行任务
    • 当currentSize>=corePoolSize、workQueue已满、并且currentSize>maximumPoolSize时,调用handler默认抛出RejectExecutionExpection异常
    • 当currentSize >corePoolSize线程,空闲时间达到keepAliveTime时,关闭空闲线程
    • 当设置allowCoreThreadTimeOut(true)时,线程池中corePoolSize线程空闲时间达到keepAliveTime也将关闭

    FixedThreadPool

    通过Executors的newFixedThreadPool方法创建,它是一种线程数量固定的线程池,当线程处于空闲状态时,它们并不会被回收,除非线程池被关闭了。当所有的线程都处于活动状态时,新任务都会处于等待状态,直到有线程空闲出来。由于FixedThreadPool只有核心线程并且这些核心线程不会被回收,这意味着它能够更加快速地响应外界的请求。

    public static ExecutorService newFixedThreadPool(int nThreads) {
        return new ThreadPoolExecutor(nThreads, nThreads,
                                      0L, TimeUnit.MILLISECONDS,
                                      new LinkedBlockingQueue<Runnable>());
    }
    

    CachedThreadPool

    通过Executors的newCachedThreadPool方法创建,它是一种线程数量不定的线程池,它只有非核心线程,并且最大线程数为Integer.MAX_VALUE,从CachedThreadPool的特性来看,这类线程池比较适合执行大量的耗时较少的任务,当整个线程池都处于闲置状态时,线程池中的线程都会超时而被停止,这个时候CachedThreadPool之中实际上是没有任何线程的,它几乎是不占用任何系统资源的。

    public static ExecutorService newCachedThreadPool() {
        return new ThreadPoolExecutor(0, Integer.MAX_VALUE,
                                      60L, TimeUnit.SECONDS,
                                      new SynchronousQueue<Runnable>());
    }
    

    ScheduledThreadPool

    通过Executors的newScheduledThreadPool方法创建,它的核心线程是固定的,非核心线程数是没有限制的,主要用于执行定时任务和具有固定周期的重复任务。

    public static ScheduledExecutorService newScheduledThreadPool(int corePoolSize) {
        return new ScheduledThreadPoolExecutor(corePoolSize);
    }
    

    SingleThreadExecutor

    通过Executors的newSingleThreadExecutor方法创建,它只有一个核心线程,确保所有任务都在同一个线程中按顺序执行,使得这些不需要处理线程同步问题。

    public static ExecutorService newSingleThreadExecutor() {
        return new FinalizableDelegatedExecutorService
            (new ThreadPoolExecutor(1, 1,
                                    0L, TimeUnit.MILLISECONDS,
                                    new LinkedBlockingQueue<Runnable>()));
    }
    
  • 相关阅读:
    44、通配符匹配
    Consul注册中心
    16.11、跳水板
    209、长度最小的子数组
    分布式CAP定理
    剑指 Offer 09、用两个栈实现队列
    git 2.33+版本升级后sshrsa认证失效问题
    OpenJDK各平台版本下载
    maven阿里云镜像无法下载gexinrpsdkbase
    2.SpringBoot集成MinIo文件服务器
  • 原文地址:https://www.cnblogs.com/fomin/p/9990130.html
Copyright © 2020-2023  润新知