线程是程序执行的上下文。单线程程序一次只能做一件事,而多线程程序一次可以做很多事情。
把它想象成餐厅的厨房。一个厨师一次只能做一项任务,比如切洋葱或把东西放进烤箱。如果收到需要厨师大量工作的订单(例如制作沙拉与将东西放入烤箱并等待),则某些餐点可能会因为厨师忙而延迟。另一方面,如果那个厨师只是要烤一堆东西,他没有太多的工作要做,他可以在等待烤箱里的食物完成的同时做其他饭菜。
如果有多名厨师,其中许多任务可以同时完成。可以同时准备许多餐点。
Apache 的线程模型就像雇佣固定数量的厨师(不管你的餐厅当晚有多少顾客),每个厨师一次只能做一顿饭。这意味着,如果有一份餐单,则会为该餐分配一名专门的厨师。厨师有时会忙着切配料和混合蛋糕面糊,但有时他只是站着等土豆煮沸。在任何给定时间,您的大多数厨师都可以闲着,等待煮土豆和烤蛋糕,并且不会再处理任何订单,因为每个厨师一次只专注于一个订单。
更糟糕的是,你的厨房只有你能负担得起的那么大。每个厨师都占用空间和资源,您可能会遇到这样一种情况,一群厨师拿着唯一可用的勺子站在周围,阻止其他厨师制作他们的食物。
Nginx 是您没有询问的另一个 Web 服务器(通常用作代理),但我将它包括在内是为了解释另一个线程模型。它还雇用固定数量的厨师,但雇用的厨师人数较少。每个厨师一次可以处理多餐。因此,如果他们在等待土豆煮熟时收到一份切碎的沙拉订单,他们可以继续做沙拉,而不是无所事事。您可以拥有一个较小的厨房(相对于餐厅的大小/顾客数量),并获得相同数量或更多的餐点。这是一个紧凑的工作人员,可以有效地不浪费时间和资源。
Node.js 有点不同。从 JavaScript 的角度来看,它是单线程的,但磁盘和网络 IO 等其他任务是在单独的线程上自动处理的。这就像拥有一个只有一名厨师的厨房,但在某些情况下这是有道理的。如果您的厨房有很多忙于该厨师的工作,那么雇用更多厨师来工作也许是有意义的。(要在 Node.js 中执行此操作,您只能生成更多进程,这实际上就像在彼此相邻的地方建造一堆小厨房。您可以让一个人站在前面协调所有这些厨房的订单。)但是,如果你只是一家面包店(主要是 IO,厨师的工作很少),也许你只需要一个厨师。
综上所述,不同的线程模型用于划分工作并有效地处理它。哪种线程模型有意义取决于您的需求以及您选择的服务器的其他特性。