泛亚电竞为什么要使用线程池?
- 降低资源消耗。线程通过重复利用已创建的线程线程,降低线程创建和销毁造成的消耗
- 提高响应速度
。当任务到达时,任务可以不需要等到线程创建就能立即执行
- 增加线程的线程可管理型。线程是线程稀缺资源,使用线程池可以进行统一分配,调优和监控
线程池的核心属性有哪些?
- threadFactory(线程工厂):用于创建工作线程的工厂 。
- corePoolSize(核心线程数):当线程池运行的线程线程少于 corePoolSize 时,将创建一个新线程来处理请求,即使其他工作线程处于空闲状态。
- workQueue(队列):用于保留任务并移交给工作线程的线程阻塞队列。
- maximumPoolSize(最大线程数):线程池允许开启的线程最大线程数
。
- handler(拒绝策略):往线程池添加任务时,将在下面两种情况触发拒绝策略:1)线程池运行状态不是线程 RUNNING;2)线程池已经达到最大线程数,并且阻塞队列已满时。
- keepAliveTime(保持存活时间):如果线程池当前线程数超过 corePoolSize,则多余的线程线程空闲时间超过 keepAliveTime 时会被终止。
线程池的线程运作流程?

线程池的5种状态?
- RUNNING:接受新任务并处理排队的任务
。
- SHUTDOWN:不接受新任务,但处理排队的线程任务。
- STOP:不接受新任务,不处理排队的线程任务,并中断正在进行的任务。
- TIDYING:所有任务都已终止,workerCount 为零,线程转换到 TIDYING 状态将运行 terminated() 钩子方法。线程
- TERMINATED:terminated() 已完成。线程

线程池有哪些队列?
- ArrayBlockingQueue:基于数组结构的有界阻塞队列,按先进先出对元素进行排序。
- LinkedBlockingQueue:基于链表结构的有界/无界阻塞队列,按先进先出对元素进行排序,吞吐量通常高于 ArrayBlockingQueue。Executors.newFixedThreadPool 使用了该队列
。
- SynchronousQueue:不是一个真正的队列,而是一种在线程之间移交的机制。要将一个元素放入 SynchronousQueue 中,必须有另一个线程正在等待接受这个元素。如果没有线程等待,并且线程池的当前大小小于最大值,那么线程池将创建一个线程,否则根据拒绝策略,这个任务将被拒绝 。使用直接移交将更高效,因为任务会直接移交给执行它的线程,而不是被放在队列中,然后由工作线程从队列中提取任务。只有当线程池是无界的或者可以拒绝任务时,该队列才有实际价值。Executors.newCachedThreadPool使用了该队列 。
- PriorityBlockingQueue:具有优先级的无界队列,按优先级对元素进行排序。元素的优先级是通过自然顺序或 Comparator 来定义的。
使用队列有什么需要注意的吗?
- 使用有界队列时,需要注意线程池满了后,被拒绝的任务如何处理
。
- 使用无界队列时,需要注意如果任务的提交速度大于线程池的处理速度,可能会导致内存溢出。
线程池有哪些拒绝策略?
- AbortPolicy:中止策略。默认的拒绝策略,直接抛出 RejectedExecutionException。调用者可以捕获这个异常,然后根据需求编写自己的处理代码
。
- DiscardPolicy:抛弃策略。什么都不做,直接抛弃被拒绝的任务 。
- DiscardOldestPolicy:抛弃最老策略 。抛弃阻塞队列中最老的任务,相当于就是队列中下一个将要被执行的任务,然后重新提交被拒绝的任务
。如果阻塞队列是一个优先队列,那么“抛弃最旧的”策略将导致抛弃优先级最高的任务,因此最好不要将该策略和优先级队列放在一起使用
。
- CallerRunsPolicy:调用者运行策略。在调用者线程中执行该任务。该策略实现了一种调节机制,该策略既不会抛弃任务,也不会抛出异常,而是将任务回退到调用者(调用线程池执行任务的主线程),由于执行任务需要一定时间,因此主线程至少在一段时间内不能提交任务,从而使得线程池有时间来处理完正在执行的任务。
线程只能在任务到达时才启动吗?
- 默认情况下,即使是核心线程也只能在新任务到达时才创建和启动。但是我们可以使用 prestartCoreThread(启动一个核心线程)或 prestartAllCoreThreads(启动全部核心线程)方法来提前启动核心线程。
核心线程怎么实现一直存活?
阻塞队列方法有四种形式,它们以不同的方式处理操作,核心线程在获取任务时,通过阻塞队列的 take() 方法实现的一直阻塞(存活)。如下表。
抛出异常 | 返回特殊值 | 一直阻塞 | 超时退出 |
插入 | add(e) | offer(e) | put(e) | offer(e,time,unit) |
移除 | remove() | poll() | take() | poll(time,unit) |
检查 | element() | peek() | 不可用 | 不可用 |
非核心线程如何实现在 keepAliveTime 后死亡?
也是利用阻塞队列的方法,在获取任务时通过阻塞队列的 poll(time,unit) 方法实现的在延迟死亡
Executors 提供了哪些创建线程池的方法?
- newFixedThreadPool:固定线程数的线程池。corePoolSize = maximumPoolSize,keepAliveTime为0,工作队列使用无界的LinkedBlockingQueue
。适用于为了满足资源管理的需求,而需要限制当前线程数量的场景,适用于负载比较重的服务器。
- newSingleThreadExecutor:只有一个线程的线程池
。corePoolSize = maximumPoolSize = 1,keepAliveTime为0, 工作队列使用无界的LinkedBlockingQueue。适用于需要保证顺序的执行各个任务的场景。
- newCachedThreadPool: 按需要创建新线程的线程池。核心线程数为0,最大线程数为 Integer.MAX_VALUE,keepAliveTime为60秒,工作队列使用同步移交 SynchronousQueue
。该线程池可以无限扩展,当需求增加时,可以添加新的线程,而当需求降低时会自动回收空闲线程。适用于执行很多的短期异步任务,或者是负载较轻的服务器