线程池的工作原理?
1. AtomicIteger ctl 一共32位,高三位表示线程池的状态,低29位表示工作线程worker的数量。
2. execute方法:
1. 小于核心线程数,就创建工作线程worker,执行任务。
2. 否则,先判断线程池状态 然后加入到workerQueue队列中(再次判断状态 不是running就从队列remove 并执行拒绝策略)这里的队列是创建线程池的时候初始化的。
3. 尝试创建非核心工作线程worker,如果失败执行拒绝策略。
4.ThreadPoolExecutor.addWorker() :
1.双重for循环不断自旋 将ctl值 cas加1,成功跳出循环,执行下面代码逻辑,状态改变或者(加核心工作线程或者加最大核心线程超过阈值直接返回false),不往下执行
2. 创建一个new worker()(worker的构造方法会ThreadFactory创建一个线程并把worker放到线程里去,因为worker本身就是一个runnable,也是一个aqs锁), reentrantLock 将worker加入到hashSet里(多线程操作共享变量)unlock
3. 加入成功启动线程,执行调用线程的 start() ,然后会调用线程的run(),然后会调用worker的run() 然后会调用runWorker() (异步调用)
4. 返回调用成功或者失败。
5. ThreadPoolExecutor.runWorker():
firstTask不为空就执行firstTask,为空则从阻塞队列里取。
调用的是worker的unlock (worker 的lock 调用父类AQS的release)先解锁,后加锁。解锁的目的是为了让外部可以中断(在shutDown的时候会中断)。
执行交给线程池runnable任务的run方法.
worker是内部类
核心配置参数: 核心线程数,最大线程数,阻塞队列,最大空闲时间,线程工厂(创建线程,更改线程名称便于生产定位),拒绝策略。
拒绝策略 四种:
1.AbortPolicy 直接抛出异常不处理
2.CallerRunsPolicy在任务被拒绝添加后,会调用当前线程池的所在的线程去执行被拒绝的任务
3.DiscardPolicy:采用这个拒绝策略,会让被线程池拒绝的任务直接抛弃,不会抛异常也不会执行。
4.DiscardOldestPolicy策略的作用是,当任务呗拒绝添加时,会抛弃任务队列中最旧的任务也就是最先加入队列的,再把这个新任务添加进去。lru.
jdk提供的线程池种类和区别?
1.newFixedThreadPool
2.newSingleThreadExecutor
3.newCachedThreadPool
4.newScheduledThreadPool
线程池的无界阻塞队列会发生什么? 满了会OOM
线程池满了之后会发生什么? 最大线程数设置过多会出现栈溢出。
机器宕机,线程池队列中的请求怎么办?
提交任务之前入库,比如 创建抓取任务, 会有任务状态, 在重启机器的时候 会搞一个钩子程序,把任务状态置为异常,机器启动会重新执行任务。