为什么需要线程池:
JVM在HotSot的线程模型下,java线程会一对一映射为内核线程,这意味着,在Java中每次创建以及回收线程都会去内核创建以及回收,这就有可能导致:创建和销毁线程所花费的时间和资源可能比处理任务花费的时间和资源要更多,线程池的出现是为了提高线程的复用性以及固定线程的数量。
线程池的好处:
- 降低资源消耗:重复利用线程池中的线程节省线程创建和销毁带来的消耗。
- 提高性能:当任务需求时,可以不用创建线程直接执行,主要是直接从线程池中取出线程去执行。
- 提高线程的可管理性:线程是稀缺资源,而且也是任务中不可缺少的资源,如果频繁且无限制的创建会消耗系统资源,降低系统稳定性导致系统崩溃,内存溢出等问题。
ThreadPoolExecutor的通用构造函数中有7个参数
- corePoolSize:当有新任务时,如果线程池中的线程数没有达到线程池的基本大小,就会创建新的线程去执行任务,否则将任务放入阻塞队列中。
- maximumPoolSize:当阻塞队列满时,如果线程池中的线程数没有超过最大线程数,则会创建新的线程执行任务,否则根据拒绝策略处理新任务。
- KeepAilveTime:非核心线程空闲之后,保持存活的时间,此参数只对肥核心线程有用。
- timeUnit:时间单位
- BlockingQueue:存储等待运行的任务
- threadFactory:每当线程池创建一个新线程时,都是通过线程工厂方法完成的
- rejectedExecutionHandler:当线程池和队列都满了,根据拒绝策略处理新任务
线程池是如何指定线程数的
首先要考虑业务是什么样的,是cpu密集性的还是io密集型的,假设运行应用的机器CPU核心数是N,那cpu密集型的可以给到N+1,io密集型的可以给到2N试试,但这只是经验性的做法,具体要开多少线程,需要进行压测才能比较准确的确定下来。 线程也不是说越大越好,多线程是为了充分利用CPU的资源,如果设置的线程过多,线程有大量上下文切换,这一部分也会带来系统的开销,这就得不偿失了。
线程池的创建
阿里巴巴开发手册有提到,不要使用Executors去创建线程,最主要的目的是:使用ThreadPoolExecutor创建的线程更能了解线程池运行的规则,避免线程耗尽的风险。