目录
像线程池/常量池/内存池/进程池等等,这些池的思想都是一样的——提高效率。
引入线程池的原因
并发编程使用多进程,线程比进程更轻量,在频繁创建销毁方面更有优势,随着时代的发展对频繁有了新的定义,现有的要求下,频繁的创建销毁线程使开销越来越明显了,那么对于这个问题该如何进行优化呢?
(1)线程池 (2)协程(也可以叫纤程,可以理解为比线程更加轻量的程序)
线程池/协程能提高效率的原因:
常规时,线程的创建销毁是要由用户态+内核态配合完成,当引入线程池/协程后可以只由用户态就可以完成,不需要和内核态配合完成。直接调用api创建销毁线程,这个过程需要内核完成,而内核完成的工作很多时候是不太可控的(可能内核还要先做别的工作,这个事情是不可控的),如果使用线程池,提前把线程创建好放到用户态中的数据结构,用的时候直接在线程池中获取,用完了再放回线程池,这个过程完全是用户态代码,不需要和内核进行交互。
协程本质也是纯用户态代码,规避内核操作,不同的是用一个内核的线程来表示多个协程,纯用户态,进行协程之间的调度。
介绍标准库中线程池的参数(高频面试题)
标准库线程池使用ThreadPoolExecutor,使用起来比较复杂,构造方法中包含很多的参数
我们一个一个来看:
(1)corePoolSize 核心线程数,在创建线程池时可以自己设定包含多少核心线程
(2)maximumPoolSize 最大线程数,是核心线程+非核心线程的总数,一个线程池刚创建时只包含核心线程数这么多的线程,线程池提供一个submit方法往里面添加任务,每个任务都是一个runnable对象,如果当前的任务较少,当前核心线程可以处理好这些任务,那么此时线程池中就只有核心线程在工作;如果任务较多,核心线程干不过来了,这个时候线程池就会创建新的线程来支撑更多的工作,这个过程称为——动态扩展。新创建的线程数就是非核心线程,新创建的非核心线程加上核心线程不能超过最大线程数。
过了一段时间后任务没那么多了,部分的非核心线程就会被GC回收掉,这样既保证了任务多时工作的效率,也保证了任务少时系统的开销小。