简介
其实也不用简介了吧,线程池这个太熟悉了,无非就是七个参数和运行过程,这个都说烂了,就略过吧。
四种线程池
- newFixedThreadPool(int nThreads)
固定线程池,线程数量是固定的,队列使用的是链表阻塞队列(LinkedBlockingQueue),队列是无限长的。 - newCachedThreadPool()
缓存线程池,核心线程数为0,最大线程数为Integer.MAX_VALUE,也就是说可以不断的新建线程,任务执行完成之后,线程都会被回收。 - newSingleThreadPool()
单个线程池,核心线程数和最大线程数都是1,但是队列是链表阻塞队列,无限长。 - newScheduledThreadPool(int corePoolSize)
周期性线程池,也就是说可以周期地执行任务,最大线程数是Integer.MAX_VALUE,可以无限创建线程,队列是DelayedWorkQueue()。 - 这四种线程池本质上都是调用的ThreadPoolExecutor构造方法
阻塞队列
- 含义:阻塞队列和一般的队列的区别就在于:一般队列在获取值时,如果队列为空,会直接返回一个空值;而阻塞队列不一样,会阻塞获取元素的线程,直到队列中有值,会唤醒获取元素的线程,获取元素返回。
- ArrayBlockingQueue(数组阻塞队列)
因为是基于数组的阻塞队列,所以在初始化的时候就会指定其大小,队列长度是固定的。 - LinkedBlockingQueue(链表阻塞队列)
链表是没有长度限制的,它的最大长度是Integer.MAX_VALUE,当然也可以指定其长度大小,newFixedThreadPool和newSingleThreadPool中都是用的这种阻塞队列,虽然大小没限制,但它依旧是一个有界的阻塞队列。 - DelayQueue(延迟阻塞队列)
只有当指定的延迟时间到了,才能获取到队列中的元素,它是一个无界的队列,所以它不会阻塞生产者,生产者可以随意往里面写入元素,但是在元素的延迟时间到之前,消费者都会阻塞住,等待延迟时间,newScheduledThreadPool就是用的这种阻塞队列。 - PriorityBlockingQueue(优先级队列)
带有优先级的阻塞队列,不再遵循队列的FIFO元素,会让优先级高的元素先出队,也是一个无界队列。 - SynchronousQueue(同步队列)
这个一个特殊的阻塞队列,它本身是不存放任何元素,也就是长度始终为0,当生产者往里面写入元素的时候,就会被阻塞住,直到有消费者取出元素才会再唤醒生产者,newCachedThreadPool用的就是这个阻塞队列。
拒绝策略
当没有空闲线程,且队列也满了的时候,线程池就会执行拒绝策略了。
- AbortPolicy
这个策略会丢弃任务,并抛出异常,这是线程池默认的拒绝策略,需要处理好抛出的异常,否则会影响后续的任务执行。 - DiscardPolicy
直接丢弃多出来的任务,不会抛出异常 - DiscardOldestPolicy
丢弃阻塞队列中最老的任务,且将新任务添加进去 - CallerRunsPolicy
使用调用者自己来执行任务,由于是调用者自己一个人执行任务,如果任务提交速度过快,可能会造成程序阻塞,导致性能下降。 - 自定义拒绝策略
实现RejectedExecutionHandle接口就可以了。