根本原因是target=func()导致函数被提前执行,线程实际运行none;正确写法是target=func, args=(...),仅传函数对象和参数元组。

这个问题很典型:代码看似起了多个线程,但实际所有任务是顺序执行的,耗时翻倍甚至更久。根本原因不是线程没创建,而是 target 函数被提前调用了一次,返回值(通常是 None)被当成了 target,导致线程真正运行时什么都没做。
错误写法:target=func() —— 函数当场执行
这是最常踩的坑。比如:
❌ 错误示例:
t = threading.Thread(target=worker("task-1"))
这行代码在主线程里就立刻执行了 worker("task-1"),把它的返回值(比如 None)传给了 target。线程启动后,其实是在运行 None——什么也不干。后续循环中每个 t 都是这样,最终只有主线程在干活,完全串行。
正确写法:target=func, args=(...) —— 只传函数名和参数
必须把函数对象本身传进去,参数单独用 args 或 kwargs 传:
- 单个参数:
args=("task-1",)(注意末尾逗号,否则会被当成字符串迭代) - 多个参数:
args=("task-1", 100, True) - 关键字参数:
kwargs={"name": "task-1", "timeout": 10}
✅ 正确示例:
t = threading.Thread(target=worker, args=("task-1",))
此时 worker 不会立即执行,线程启动后才调用它,并传入 "task-1"。
快速自查与修复步骤
- 检查所有
threading.Thread(...)构造语句,确认target=后面是不是带了括号;有括号基本就是错的 - 把
target=func(x)全部替换成target=func, args=(x,) - 加一行简单日志验证是否真并发:在 worker 开头加
print(f"{threading.current_thread().name} started"),看输出是否交错出现 - 计时对比:修复前后跑同一组任务,串行耗时 ≈ 单任务×线程数,修复后应接近单任务耗时(忽略调度开销)
进阶提醒:别让 print 或 logging 假装“并发”
即使线程真并发了,如果所有线程都直接调 print() 或往同一个文件写日志,输出仍可能看起来串行或错乱——这不是线程没跑,是 I/O 竞争掩盖了并发性。这时要区分问题层级:先确认线程是否真启动(用时间戳或计数器),再解决日志/输出同步问题。











