Java相关文章
线程池参数
- corePoolSize 线程池核心线程数
- 线程池中会维护一个最小的线程数量,即使这些线程处理空闲状态,他们也不会被销毁,除非设置了allowCoreThreadTimeOut。这里的最小线程数量即是corePoolSize。
- maximumPoolSize 线程池最大线程数量
- 一个任务被提交到线程池以后,首先会找有没有空闲存活线程,如果有则直接将任务交给这个空闲线程来执行,如果没有则会缓存到工作队列(后面会介绍)中,如果工作队列满了,才会创建一个新线程,然后从工作队列的头部取出一个任务交由新线程来处理,而将刚提交的任务放入工作队列尾部。线程池不会无限制的去创建新线程,它会有一个最大线程数量的限制,这个数量即由maximunPoolSize指定。
- keepAliveTime 空闲线程存活时间
- 一个非核心线程如果处于空闲状态,并且当前的线程数量大于corePoolSize,那么在指定时间后,这个空闲线程会被销毁,这里的指定时间由keepAliveTime来设定
- unit 空闲线程存活时间单位
- keepAliveTime的计量单位
- workQueue 工作队列
- ArrayBlockingQueue
- 数组有界大小固定
- 基于数组的有界阻塞队列,按FIFO排序。新任务进来后,会放到该队列的队尾,有界的数组可以防止资源耗尽问题。当线程池中线程数量达到corePoolSize后,再有新任务进来,则会将任务放入该队列的队尾,等待被调度。如果队列已经是满的,则创建一个新线程,如果线程数量已经达到maxPoolSize,则会执行拒绝策略。
- LinkedBlockingQuene
- 链表有界大小可变
- 基于链表的无界阻塞队列(其实最大容量为Interger.MAX),按照FIFO排序。由于该队列的近似无界性,当线程池中线程数量达到corePoolSize后,再有新任务进来,会一直存入该队列,而不会去创建新线程直到maxPoolSize,因此使用该工作队列时,参数maxPoolSize其实是不起作用的。
- SynchronousQuene
- SynchronousQueue的capacity是0,该队列不存储任何元素
- 也就是说SynchronousQueue的每一次insert操作,必须阻塞到其他线程的remove操作。而每一个remove操作也必须阻塞其他线程的insert操作。
- PriorityBlockingQueue
- 具有优先级的无界阻塞队列,优先级通过参数Comparator实现。
- 队列管理任务方法
抛出异常 |
特殊值 |
阻塞 |
超时 |
|
插入 |
||||
移除 |
||||
检查 |
不可用 |
不可用 |
handler 拒绝策略
- CallerRunsPolicy
- 该策略下,在调用者线程中直接执行被拒绝任务的run方法,除非线程池已经shutdown,则直接抛弃任务。
- AbortPolicy
- 该策略下,直接丢弃任务,并抛出RejectedExecutionException异常。
- DiscardPolicy
- 该策略下,直接丢弃任务,什么都不做。
- DiscardOldestPolicy
- 该策略下,抛弃进入队列最早的那个任务,然后尝试把这次拒绝的任务放入队列
线程池核心线程数为0任务怎么创建
- 当核心线程数为0的时候,会创建一个非核心线程进行执行
- 核心线程数不为0的时候,如果核心线程数在执行,会有一个非核心线程数从队列中取对象执行线程
- 核心线程数执行的是队列的take,非核心线程数执行队列的offer和poll
- 核心线程数不为0且队列为SynchronousQueue时,就成了单线程运行了
线程池一个任务从被提交到被执行,线程池做了哪些工作?
- 线程池刚创建时,里面没有一个线程。任务队列是作为参数传进来的。不过,就算队列里面有任务,线程池也不会马上执行他们。
- 当调用execute()方法添加一个任务时,线程池会做如下判断:
- 如果正在运行的线程数量小于corePoolSize,那么马上创建线程运行这个任务
- 如果正在运行的线程数量大于或等于corePoolSize,那么将这个任务放入队列
- 如果这时候队列满了,而且正在运行的线程数量小于maximunPoolSize,那么还是要创建非核心线程立刻运行这个任务
- 如果队列满了,而且正在运行的线程数量大于或等于maximunPoolSize,那么线程池会抛出RejectedExecutionException
- 当一个线程完成任务时,它会从队列中取下一个任务来执行
- 当一个线程无事可做,超过一定的时间(keepAliveTime)时,线程池会判断,如果当前运行的线程数大于corePoolSize,那么这个线程就被停掉。所以线程池的所有任务完成后,它最终会收缩到corePoolSize的大小
常见线程池有哪些
- newCachedThreadPool创建一个可缓存线程池,如果线程池长度超过处理需要,可灵活回收空闲线程,若无可回收,则新建线程。
- newFixedThreadPool 创建一个定长线程池,可控制线程最大并发数,超出的线程会在队列中等待。
- newScheduledThreadPool 创建一个定长线程池,支持定时及周期性任务执行。
- newSingleThreadExecutor 创建一个单线程化的线程池,它只会用唯一的工作线程来执行任务,保证所有任务按照指定顺序(FIFO, LIFO, 优先级)执行。