线程池三问—百度真题

Posted 码上积木

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了线程池三问—百度真题相关的知识,希望对你有一定的参考价值。

线程分为主线程和子线程,主线程用于处理界面相关事情,子线程用于执行耗时操作。所以子线程的任务管理就格外重要,线程池就是这个管理的角色。今天的三问是关于线程池的:

  • 线程池是干嘛的,优点有哪些?
  • 线程池的构造方法每个参数是什么意思,执行任务的流程
  • android线程池主要分为哪几类,分别代表了什么?

线程池是干嘛的,优点有哪些?

线程池主要用作管理子线程,优点有:

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

线程池的构造方法每个参数是什么意思,执行任务的流程

    public ThreadPoolExecutor(int corePoolSize,
                              int maximumPoolSize,
                              long keepAliveTime,
                              TimeUnit unit,
                              BlockingQueue<Runnable> workQueue,
                              ThreadFactory threadFactory,
                              RejectedExecutionHandler handler)
 
{}
  • corePoolSize:核心线程数。默认情况下线程池是空的,只是任务提交时才会创建线程。如果当前运行的线程数少于corePoolSize,则会创建新线程来处理任务;如果等于或者等于corePoolSize,则不再创建。如果调用线程池的prestartAllcoreThread方法,线程池会提前创建并启动所有的核心线程来等待任务。
  • maximumPoolSize:线程池允许创建的最大线程数。如果任务队列满了并且线程数小于maximumPoolSize时,则线程池仍然会创建新的线程来处理任务。
  • keepAliveTime:非核心线程闲置的超时事件。超过这个事件则回收。如果任务很多,并且每个任务的执行时间很短,则可以调大keepAliveTime来提高线程的利用率。另外,如果设置allowCoreThreadTimeOut属性来true时,keepAliveTime也会应用到核心线程上。
  • TimeUnit:keepAliveTime参数的时间单位。可选的单位有天Days、小时HOURS、分钟MINUTES、秒SECONDS、毫秒MILLISECONDS等。
  • workQueue:任务队列。如果当前线程数大于corePoolSzie,则将任务添加到此任务队列中。该任务队列是BlockingQueue类型的,即阻塞队列。
  • ThreadFactory:线程工厂。可以使用线程工厂给每个创建出来的线程设置名字。一般情况下无须设置该参数。
  • RejectedExecutionHandler:拒绝策略。这是当前任务队列和线程池都满了时所采取的应对策略,默认是AbordPolicy,表示无法处理新任务,并抛出RejectedExecutionException异常。

其中,拒绝策略有四种:

  • AbordPolicy:无法处理新任务,并抛出RejectedExecutionException异常。
  • CallerRunsPolicy:用调用者所在的线程来处理任务。此策略提供简单的反馈控制机制,能够减缓新任务的提交速度。
  • DiscardPolicy:不能执行的任务,并将该任务删除。
  • DiscardOldestPolicy:丢弃队列最近的任务,并执行当前的任务。

执行任务流程:

  • 如果线程池中的线程数量未达到 核心线程的数量,会直接启动一个核心线程来执行任务。
  • 如果线程池中的线程数量已经达到或者超过核心线程的数量,那么任务会被插入到 任务队列中排队等待执行。
  • 如果任务队列无法插入新任务,说明任务队列已满,如果未达到规定的最大线程数量,则启动一个 非核心线程来执行任务。
  • 如果线程数量超过规定的最大值,则执行 拒绝策略-RejectedExecutionHandler。

Android线程池主要分为哪几类,分别代表了什么?

主要有四类:FixedThreadPool、CachedThreadPool、SingleThreadExecutor、ScheduledTheadPool

1) FixedThreadPool——可重用固定线程数的线程池

    public static ExecutorService newFixedThreadPool(int nThreads) {
        return new ThreadPoolExecutor(nThreads, nThreads,
                                      0L, TimeUnit.MILLISECONDS,
                                      new LinkedBlockingQueue<Runnable>());
    }
  • 线程 数量固定且都是核心线程:核心线程数量和最大线程数量都是nThreads;
  • 都是核心线程且不会被回收,快速相应外界请求;
  • 没有超时机制,任务队列也没有大小限制;
  • 新任务使用 核心线程处理,如果没有空闲的核心线程,则排队等待执行。
  1. CachedThreadPool——按需创建的线程池
    public static ExecutorService newCachedThreadPool() {
        return new ThreadPoolExecutor(0, Integer.MAX_VALUE,
                                      60L, TimeUnit.SECONDS,
                                      new SynchronousQueue<Runnable>());
    }
  • 线程数量不定,只有非核心线程,最大线程数 任意大:传入核心线程数量的参数为0,最大线程数为Integer.MAX_VALUE;
  • 有新任务时使用 空闲线程执行,没有空闲线程则创建新的线程来处理。
  • 该线程池的每个空闲线程都有超时机制,时常为60s(参数:60L, TimeUnit.SECONDS),空闲超过60s则回收空闲线程。
  • 适合执行大量的耗时较少的任务,当所有线程闲置 超过60s都会被停止,所以这时几乎不占用系统资源。
  1. SingleThreadExecutor——单线程的线程池
    public static ExecutorService newSingleThreadExecutor() {
        return new FinalizableDelegatedExecutorService
            (new ThreadPoolExecutor(11,
                                    0L, TimeUnit.MILLISECONDS,
                                    new LinkedBlockingQueue<Runnable>()));
    }
  • 只有 一个核心线程,所有任务在同一个线程按顺序执行。
  • 所有的外界任务统一到一个线程中,所以不需要处理线程同步的问题。
  1. ScheduledThreadPool——定时和周期性的线程池
    private static final long DEFAULT_KEEPALIVE_MILLIS = 10L;

    public ScheduledThreadPoolExecutor(int corePoolSize) {
        super(corePoolSize, Integer.MAX_VALUE,
              DEFAULT_KEEPALIVE_MILLIS, MILLISECONDS,
              new DelayedWorkQueue());
    }
  • 核心线程 数量固定,非核心线程数量 无限制
  • 非核心线程闲置超过10s会被回收;
  • 主要用于执行定时任务和具有固定周期的重复任务;

参考链接

线程池讲解

码上积木 发起了一个读者讨论 留言区~


以上是关于线程池三问—百度真题的主要内容,如果未能解决你的问题,请参考以下文章

C#多线程之旅

百度真题之走迷宫

2021百度Java岗面试真题收录解析,看完这一篇你就懂了

华为OD机试真题Java实现单词反转真题+解题思路+代码(2022&2023)

百度真题之城市规划(连通域数目)

华为OD机试真题Python实现翻转单词顺序真题+解题思路+代码(2022&2023)