一、为什么要使用线程池:
1、统一管理,可以控制最大线程数量,避免线程数过多造成内存不足;
2、线程频繁创建和销毁比较耗费性能,使用线程池可以重用线程,避免线程的频繁创建和销毁,提高性能。
3、直接创建线程的方式,功能比较单一,使用线程池可以实现定时任务,还能使用Future接收线程返回的处理结果。
二、几种常见的线程池
1、缓存线程池,Executors.newCachedThreadPool();其corePoolSize数量为0,线程池中所有线程都是非核心线程,所以任务执行完,并且过了60秒后线程都会销毁,比较节省资源,适用于任务量大,耗时短的场景。
2、定长线程池,Executors.newFixedThreadPool();需要设定核心线程数,其核心线程数和最大线程数一样,适用于任务量固定,耗时长的场景。
3、单一线程池,Executors.newSingledThreadPool();线程池中只有一个线程,所以进入线程池中的任务将会被同一个线程处理,而且任务是按添加的先后顺序被执行的,适用于多个任务顺序执行的场景。
4、定时线程池,Executors.newScheduledThreadPool();需要设定核心线程数,非核心线程数无限制,keepAliveTime为0,非核心线程一旦闲置就被回收。适用于执行定时任务和周期性重复任务。scheduledAtFixedRate()方法就是执行重复任务。
5、Timer和ScheduledThreadPool
Timer定时器在执行多个任务时,不同任务之间会互相影响,若先执行的任务发生异常,后面的任务就执行不了。一般执行定时任务都使用定时任务线程池。
三、线程池任务执行流程
①当线程数小于corePoolSize时,新建线程处理任务;
②当线程数等于corePoolSize时,新的任务进入阻塞队列workQueue等待;
③当workQueue容量已满,线程池中线程数小于maxmumPoolSize时,新建救急线程处理新任务;
④当线程数大于maxmumPoolsize时,再有新任务来就交给拒绝策略处理器RejectedExceptionHandler处理;
⑤当线程池中无任务需要处理时,超出corePoolSize的线程经过keepAliveTime之后被回收;
三、处理线程池任务异常
1、try、catch捕获异常;
2、使用线程池的submit方法提交任务,然后用Future接收结果,如果发生异常,future的get方法就会得到异常信息。
四、不推荐使用以上四种线程池的原因
这四种线程池默认的任务队列workQueue的容量为Integer.MAX_VALUE,容易造成系统崩溃。阿里规约推荐使用new ThreadPoolExcutor()的方式自定义线程池,指定各个参数的具体值,尤其是任务队列的长度。
原文:https://www.cnblogs.com/dust-to-dust/p/14724003.html