你说的那是速度上限,多线程提升的是平均速度

咱们先明确这里的多线程下载指的是单点形式的 HTTP 协议,而不是 BT、电驴之类支持多点下载的特殊协议。它们多线程下载快是因为同时会从多个不同的服务器(对于 P2P 而言甚至不一定是服务器、你开着的客户端本身就会是别人的下载节点)上获取资源,所以快,这很好理解。

对于服务器而言(或者说提供文件下载的那台机器),在同一时间内是可以为多个客户端提供服务的。那么在理想情况下,这台服务器会把自身的资源(这里具体的讲就是带宽了)为每个客户端均等分。

比如说服务器带宽总共是 10Mbps,那么有一个客户端去下载,这一个客户端就是独享这 10Mbps;有两个客户端,就每个是 5Mbps;有十个那就是每个是 1Mbps …… 依此类推。

当然了,现实中服务器即便同一时间只有一个客户端时、一般也不会让这个客户端独占自己的全部资源,会留有余地(也就是会有一个阈值上限),但这个不影响后面我要讲的,所以就先不展开了。

那么有的客户端就动了小心思了:虽然我只有一个客户端、但如果我能让服务器以为我是 N 个客户端、这样服务器不就可以为我分配更多的资源了么?

于是乎多线程这里就派上用场了(严格来说其实不是多线程、而是多个 Socket 链接,但在下载程序的实现上往往每个 Socket 链接由一个单独线程去管理,所以看起来是多线程)。

注意这里还有一个隐含的前提,就是每个线程尝试去下载的部分需要是不同的部分,最后再“组合”起来,这样才是快 —— 不然每个线程都从第 1 个字节下载、下载一百遍又有啥用?而 HTTP 协议本身是天然支持 Range 分片的,所以这点上就无需特殊考虑了。


但你开“分身”了、别人也可以开啊,最后就变成比谁开的链接多了。这就好比十个馒头,本来十个人分、一人一个正好;结果你一个人去领了两回,你是吃饱得更快了,那其余九个人就只能分剩下那八个了。

到了服务器那里人家也不傻,心说这帮孙子不讲武德啊。你不是开多个链接吗?但你第一次来我就记录下来你的 IP、你后面再有新的链接过来我就不给你资源了,直到你前面一个链接释放掉才行,大家都乖♂乖♂排♂队。


所以有的时候你即便开了多线程下载也未必能提速,得看人家服务器支不支持了(支持 Range + 支持同一个 IP 多链接)。