工作过程
(1)通过execute方法添加任务时,如果工作线程数小于corePoolSize,则创建一个新线程并执行该任务。注:新创建的线程会通过while循环不断从阻塞队列获取任务执行。
(2)如果工作线程数大于等于corePoolSize,则将任务添加到阻塞队列。
(3)如果阻塞队列满了,则判断工作线程数是否小于maximumPoolSize,如果小于则创建新线程并执行该任务;否则调用handler拒绝策略。
构造方法
(1)corePoolSize:线程池的核心线程数,即使线程池里没有任何任务,也会有corePoolSize个线程在等待任务。
(2)maximumPoolSize:最大线程数,不管你提交多少任务,线程池里最大工作线程数就是maximumPoolSize。
(3)keepAliveTime:线程存活时间。当设置corePoolSize等于maximumPoolSize时,这个字段实际不起作用,设置为0就可以;当设置corePoolSize小于maximumPoolSize时,如果工作线程数超过了corePoolSize,且后续没有任务进来,workQueue为空,这时超出corePoolSize的线程会在等待keepAliveTime时间后退出。
(4)unit:用来指定keepAliveTime的单位,比如秒:TimeUnit.SECONDS。
(5)workQueue:阻塞队列,提交的任务会被放到这个队列里。
(6)threadFactory:线程工厂,用来创建线程。
(7)handler:拒绝策略,当workQueue满了且工作线程数达到了maximumPoolSize,此时如果有新的任务进来,会触发拒绝策略。
执行任务逻辑
线程调用runWoker方法,通过while循环从getTask方法(实际是从workerQueue取任务)读取任务并执行。只要getTask方法不返回null,线程就不会退出。
获取任务过程
getTask方法实际是从workerQueue取任务。如果工作线程数大于corePoolSize,则会调用workQueue的poll方法获取任务,超时时间是keepAliveTime。如果超过keepAliveTime时长,poll返回了null,上面提到的while循序就会退出,线程也就退出了。如果工作线程数小于等于corePoolSize,则会调用workQueue的take方法阻塞在当前直到有新的任务进来。
总结
线程池大小最好是corePoolSize和maximumPoolSize保持一致,不要超过CPU核数的3倍,如果是纯计算任务(包括同机房的redis服务),只有很少的网络或者磁盘IO,那么线程池大小设置为CPU核数的2倍比较合理。
领取专属 10元无门槛券
私享最新 技术干货