跳到正文

线程

Thread

高级通用

线程(Thread)是进程内执行任务的一条路径,同一进程的多个线程可以共享内存。它能让服务在等待文件、数据库或外部接口返回时处理其他任务,例如同时查询多个彼此独立的接口。

你可能会说:「后台查几个外部接口时总是一个等完才查下一个,能不能让它们同时进行?」

读之前建议先了解(这是一个高级概念)

动手看看

查价格查库存商品页价格线程库存线程共享内存同一进程
1

商品页要同时显示价格和库存。服务在同一个进程里安排两条线程,分别处理这两个互不依赖的查询。

要点

  1. 1

    同一进程内可以有多条执行路径

    你可以把一次查询交给一个线程,主线程继续安排其他查询。操作系统会调度这些线程;它们看起来能同时推进,但是否在多个核心上并行执行,还取决于运行环境。

  2. 2

    等待外部结果时仍能推进别的任务

    假设后台要分别向两个服务查订单信息。如果所用客户端会阻塞等待,就可以让两个查询在线程中发起,减少串行等待;实际耗时仍受外部服务和线程数量影响。

  3. 3

    共享数据方便,也会带来竞争

    线程能访问同一进程的对象,所以传递结果比较方便。但两个线程若同时修改一份库存计数,就可能互相覆盖。遇到共享可变数据,我们要明确由谁修改,必要时用锁等机制协调。

容易混淆的地方

进程通常有各自的内存空间,线程则属于进程并共享其内存,所以线程间交换数据方便,隔离性也更弱。协程也能让等待中的任务让出执行机会,但通常靠程序在适当位置主动切换;线程由操作系统调度。开了多个线程也不等于计算一定能并行提速。

什么时候用

适合用

  • 后台调用几个彼此独立、会阻塞等待的外部接口时,可以用有数量上限的线程池并发查询。
  • 服务要处理文件读写等阻塞操作,又不想让当前执行路径一直等着时,可以交给工作线程。
  • 接入只提供同步调用方式的第三方库,同时还要处理其他请求时,可以考虑把调用放入受控线程池。

不适合用

  • 只是想让页面在请求期间显示加载状态,不需要改用后端线程;在前端管理请求状态就能实现。
  • 所用接口已经提供非阻塞异步调用,而且服务也采用异步架构时,通常直接用异步任务更合适。
  • 任务是大量独立的纯计算,目标是用多个 CPU 核心提速时,先评估多进程或专门的计算任务方案。

练一练

你在做一个订单后台:一次请求要查询三个互不依赖的外部服务,客户端库都是阻塞式调用。现在代码依次查询,等待时间较长。哪种改法更合适?

让 AI 帮你做

请检查订单查询接口中三个互不依赖的阻塞式外部调用。如果适合用线程,请通过有上限的线程池并发执行,保留每个调用的超时与错误处理,汇总结果后返回;同时说明共享数据如何处理,并补充并发与部分失败的测试。

接下来学什么