1. 线程池相关核心线程满了线程放哪里?阻塞队列满了放哪里?基本线程和阻塞队列都满了放哪里?
核心参数:
- int corePoolSize, // 线程池长期维持的线程数,即使线程处于Idle状态,也不会回收。 int
- maximumPoolSize, // 线程数的上限 long keepAliveTime, TimeUnit unit, //
- 超过corePoolSize的线程的idle时长,超过这个时间,多余的线程会被回收。 BlockingQueue
- workQueue, // 任务的排队队列 ThreadFactory threadFactory, // 新线程的产生方式
- RejectedExecutionHandler handler) // 拒绝策略
执行顺序:corePoolSize -> 任务队列 -> maximumPoolSize -> 拒绝策略
核心线程池满了会将线程放入阻塞队列,如果队列满了,则会创建新的线程,当线程池线程大于最大线程后再进入的线程会执行拒绝策略;
2. 拒绝策略有哪些?
如图:实现了四种拒绝策略
AbortPolicy: 抛出RejectedExecutionException
DiscardPolicy: 什么也不做,直接忽略
DiscardOldestPolicy: 丢弃执行队列中最老的任务,尝试为当前提交的任务腾出位置
CallerRunsPolicy :直接由提交任务者执行这个任务
3. 几种线程池?哪些参数不一样?
一共分为12种构造方式6大类线程池;
- newCachedThreadPool()
缓存线程以便重复使用,如果限制 60 秒没被使用,则会被移除缓存;用的是SynchronousQueue队列;队列长度为 Integer.MAX_VALUE; - newFixedThreadPool(int nThreads)
创建一个数量固定的线程池;用的是LinkedBlockingQueue队列;队列长度为 Integer.MAX_VALUE;固定数量的线程池,并且corePoolSize=maximumPoolSize - newSingleThreadExecutor()
创建一个单线程线程池。用的是LinkedBlockingQueue队列;队列长度为 Integer.MAX_VALUE; - newScheduledThreadPool(int corePoolSize)
创建一个数量固定的线程池,支持执行定时性或周期性任务;用的是DelayedWorkQueue队列; - newSingleThreadScheduledExecutor()
单线程的 newScheduledThreadPool,延迟或定时执行 - newWorkStealingPool()
Java 8 新增创建线程池的方法,使用ForJoinPool创建,ForkJoinPool适合cpu密集型任务newWorkStealingPool适合使用在很耗时的操作
4. 线程池的阻塞队列为什么不用ArrayList?
- 阻塞队列在于阻塞功能,阻塞队列拥有阻塞的取和放方法,运用到线程池中,当任务队列满后,队列将阻塞,而且队列不进行放入和扩容,当队列有空间后,线程将自动放入队列,不需要人工放入,同时从队列中取任务,如果队列中没有任务将阻塞,如果有任务村子将自动取出,也不需要人工取。