介绍一篇总结的很好的博客:https://blog.csdn.net/qq_25806863/article/details/71126867
一、概述
线程池:是创建多个线程并且进行管理的容器。(线程池是个容器,可以创建线程和管理线程,并且给线程分配任务)。
在Java中创建一个线程其实是一个很简单的事情,只要new Thread就可以了,但是这样做并不是一种很好的方式:
比如在一个项目里,全部都是用的new Thread的方式去启用线程,那么创建好Thread1,而1在运行的时候,创建了Thread2,等等等... 创建了10个线程的时候,1,2,3都执行完毕了但是没被销毁,就可能导致无限制的新建线程,相互竞争,占用过多的系统资源,导致死锁以及OOM。
而且这些线程缺乏统一的管理的功能,也缺乏定期执行,定时执行,线程中断的功能。
二、使用线程池的好处
(1) 重用已经存在的线程,减少了线程的创建和销毁的开销。
(2)可有效控制最大并发的线程数,提高了系统资源的使用率避免很多竞争,避免了OOM啊 死锁啊等。
(3)可以提供定时和定期的执行方式,单线程,并发数量的控制等功能!
三、五种类型线程池
newSingleThreadExecutor
:一个单线程的线程池,可以用于需要保证顺序执行的场景,并且只有一个线程在执行。
newFixedThreadPool
:一个固定大小的线程池,可以用于已知并发压力的情况下,对线程数做限制。
newCachedThreadPool
:一个可以无限扩大的线程池,比较适合处理执行时间比较小的任务。
newScheduledThreadPool
:可以延时启动,定时启动的线程池,适用于需要多个后台线程执行周期任务的场景。newWorkStealingPool
:一个拥有多个任务队列的线程池,可以减少连接数,创建当前可用cpu数量的线程来并行执行。
在《阿里巴巴java开发手册》中指出了线程资源必须通过线程池提供,不允许在应用中自行显示的创建线程,这样一方面是线程的创建更加规范,可以合理控制开辟线程的数量;另一方面线程的细节管理交给线程池处理,优化了资源的开销。
而线程池不允许使用Executors去创建,而要通过ThreadPoolExecutor方式,这一方面是由于jdk中Executor框架虽然提供了如newFixedThreadPool()、newSingleThreadExecutor()、newCachedThreadPool()等创建线程池的方法,但都有其局限性,不够灵活;另外由于前面几种方法内部也是通过ThreadPoolExecutor方式实现,使用ThreadPoolExecutor有助于大家明确线程池的运行规则,创建符合自己的业务场景需要的线程池,避免资源耗尽的风险。
四、创建线程池
一、可以使用工具类Executors的静态方法来获取线程池或静态方法:
- ExecutorService service1 = Executors.newSingleThreadExecutor();
- ExecutorService service2 = Executors.newCacheThreadPool();
- ExecutorService service3 = Executors.newFixedThreadPool(10);
- ExecutorService service4 = Executors.newScheduledThreadPool(10);
二、可以使用过工具类ThreadPoolExecutor,通过构造方法的一系列参数,来构成不同配置的线程池。常用的构造方法有下面四个:
ThreadPoolExecutor(int corePoolSize,
int maximumPoolSize,
long keepAliveTime,
TimeUnit unit,
BlockingQueue<Runnable> workQueue)
ThreadPoolExecutor(int corePoolSize,
int maximumPoolSize,
long keepAliveTime,
TimeUnit unit,
BlockingQueue<Runnable> workQueue,
ThreadFactory threadFactory)
ThreadPoolExecutor(int corePoolSize,
int maximumPoolSize,
long keepAliveTime,
TimeUnit unit,
BlockingQueue<Runnable> workQueue,
RejectedExecutionHandler handler)
ThreadPoolExecutor(int corePoolSize,
int maximumPoolSize,
long keepAliveTime,
TimeUnit unit,
BlockingQueue<Runnable> workQueue,
ThreadFactory threadFactory,
RejectedExecutionHandler handler)
- corePoolSize
核心线程数,默认情况下核心线程会一直存活,即使处于闲置状态也不会受存keepAliveTime限制。除非将allowCoreThreadTimeOut设置为true。
- maximumPoolSize
线程池所能容纳的最大线程数。超过这个数的线程将被阻塞。当任务队列为没有设置大小的LinkedBlockingDeque时,这个值无效。
- keepAliveTime
非核心线程的闲置超时时间,超过这个时间就会被回收。
- unit
指定keepAliveTime的单位,如TimeUnit.SECONDS。当将allowCoreThreadTimeOut设置为true时对corePoolSize生效。
- workQueue
线程池中的任务队列.
常用的有三种队列,SynchronousQueue,LinkedBlockingDeque,ArrayBlockingQueue。
- threadFactory
线程工厂,提供创建新线程的功能。ThreadFactory是一个接口,只有一个方法