JVM 中的线程与操作系统的线程是一对一的关系,所以在 JVM 中每创建一个线程就需要调用操作系统提供的 API 创建线程,赋予资源,并且销毁线程同样也需要系统调用。
而系统调用就意味着上下文切换等开销,并且线程也是需要占用内存的,而内存也是珍贵的资源。
因此线程的创建和销毁是一个重操作,并且线程本身也占用资源。
然后你还需要知道,线程数并不是越多越好。
我们都知道线程是 CPU 调度的最小单位,在单核时代,如果是纯运算的操作是不需要多线程的,一个线程一直执行运算即可。但如果这个线程正在等待 I/O 操作,此时 CPU 就处于空闲状态,这就浪费了 CPU 的算力,因此有了多线程,在某线程等待 I/O 等操作的时候,另一个线程顶上,充分利用 CPU,提高处理效率。
CPU 的核心数有限,同时能运行的线程数有限,所以需要根据调度算法切换执行的线程,而线程的切换需要开销,比如替换寄存器的内容、高速缓存的失效等等。
<<======>>
------------->
因为线程数太少无法充分利用 CPU ,太多的话由于上下文切换的消耗又得不偿失,所以我们需要评估系统所要承载的并发量和所执行任务的特性,得出大致需要多少个线程数才能充分利用 CPU,因此需要控制线程数量。
又因为线程的创建和销毁是一个“重”操作,所以我们需要避免线程频繁地创建与销毁,因此我们需要缓存一批线程,让它们时刻准备着执行任务。
目标已经很清晰了,弄一个池子,里面存放约定数量的线程,这就是线程池,一种池化技术。
注释:一般池化技术的使用方式是从池子里拿出资源,然后使用,用完了之后归还;线程池的常见实现更像是一个黑盒存在,我们设置好线程池的大小之后,直接往线程池里面丢任务,然后就不管了。线程池其实是一个典型的生产者-消费者模式。
线程池内部会有一个队列来存储我们提交的任务,而内部线程不断地从队列中索取任务来执行,这就是线程池最原始的执行机制。
线程池把任务的提交和任务的执行剥离开来,当一个任务被提交到线程池之后:
线程池de几种状态:
原文:https://www.cnblogs.com/KL2016/p/14980459.html