通过实验研究“线程池中线程数目的变化规律”
线程的运行过程可以描述如下(为了叙述方便,我们假设下限为10,上限为20):
1.当线程池被创建后,里面就会创建10个空线程(和下限值相同)。
2.当我们向线程池中排入一个任务后,就会有一个空线程接手该任务,然后运行起来。随着我们不断向线程池中排入任务,线程池中的空线程逐一接手并执行任务。
3.随着任务的不断增加,在某一时刻任务数量会超出下限,这时线程的数量就不够用了,但线程池并不会立即创建新线程,而是等待大约500毫秒左右,这么做的目的是看看在这段时间内是否有其他线程完成任务来接手这个请求,这样就可以避免因创建新线程而造成的消耗。如果这段时间内没有线程完成任务,就创建一个新线程去执行新任务。
4.在任务数量超过下限后,随着新任务的不断排入,线程池中线程数量持续增加,直至线程数量达到上限值为止。
5.当线程数量达到上限时,继续增加任务,线程数量将不再增加。比如你向线程池中排入50个任务,则只有20个进入线程池(和上限相同),另外30个在线程池外排队等待。当线程池中的某个线程完成任务后,并不会立即终止,而是从等待队列中选择一个任务继续执行,这样就减少了因创建和销毁线程而消耗的时间。
6.随着任务逐步完成,线程池外部等候的任务被逐步调入线程池,任务的数量逐步减少,但线程的数量保持恒定,始终为20(和上限值相同)。
7.随着任务被逐步完成,总有某一时刻,任务数量会小于上限值,这时线程池内多余的线程会在空闲2分钟后被释放并回收相关资源。线程数目逐步减少,直到达到下限值为止。
8.当任务数量减小到下限值之下时,线程池中的线程数目保持不变(始终和下限值相同),其中一部分在执行任务,另一部分处于空运行状态。
9.当所有任务都完成后,线程池恢复初始状态,运行10个空线程。
由上面的论述可以看出线程池提高效率的关键是一个线程完成任务后可以继续为其他任务服务,这样就可以使用有限的几个固定线程轮流为大量的任务服务,从而减少了因频繁创建和销毁线程所造成的消耗。
此外,别处写道
“glib里的threadpool,可以设置最大线程数量,最小线程数量,最长等待时间,最多空闲线程数,完全符合你所提的要求。 而且glib里的 threadpool实现的代码也很短。
个人觉得上面有人提及的最佳线程数没有任何实际意义。
比如i7,4核8线程,做纯数学运算,应该开4个线程。
但是,写web server,可以开几十个或是上百个线程。”