96 lines
4.1 KiB
Markdown
96 lines
4.1 KiB
Markdown
# Python 线程
|
||
|
||
> 原文:[https://python.land/python-concurrency/python-threads](https://python.land/python-concurrency/python-threads)
|
||
|
||
既然我们已经[设置了基线](https://python.land/python-concurrency/setting-the-baseline),我们可以尝试通过使用 Python 线程库来提高代码的速度。您很快就会发现,当您的软件受 CPU 限制时,线程就没有多大用处了。这就是为什么我还将展示 IO 绑定软件如何从线程化中获得巨大好处。如果你需要一个关于 IO 绑定和 CPU 绑定之间的区别的提示,请首先阅读我关于 [Python 并发性](https://python.land/python-concurrency)的文章。
|
||
|
||
目录
|
||
|
||
|
||
|
||
* [一个 CPU 绑定的 Python 线程示例](#A_CPU-Bound_Python_threading_example "A CPU-Bound Python threading example")
|
||
* [一个 IO 绑定的 Python 线程示例](#An_IO-Bound_Python_threading_example "An IO-Bound Python threading example")
|
||
* [继续学习](#Keep_learning "Keep learning")
|
||
|
||
|
||
|
||
## 一个 CPU 绑定的 Python 线程示例
|
||
|
||
在下面的例子中,我们使用多线程来运行我们的*重* [函数](https://python.land/introduction-to-python/functions),再次运行 80 次。每次调用都有自己的线程:
|
||
|
||
```py
|
||
import threading
|
||
import time
|
||
|
||
# A CPU heavy calculation, just
|
||
# as an example. This can be
|
||
# anything you like
|
||
def heavy(n, myid):
|
||
for x in range(1, n):
|
||
for y in range(1, n):
|
||
x**y
|
||
print(myid, "is done")
|
||
|
||
def threaded(n):
|
||
threads = []
|
||
|
||
for i in range(n):
|
||
t = threading.Thread(target=heavy, args=(500,i,))
|
||
threads.append(t)
|
||
t.start()
|
||
|
||
for t in threads:
|
||
t.join()
|
||
|
||
if __name__ == "__main__":
|
||
start = time.time()
|
||
threaded(80)
|
||
end = time.time()
|
||
print("Took: ", end - start)
|
||
```
|
||
|
||
这个线程版本在我的系统上运行大约需要 47 秒。如果繁重的函数有很多阻塞 IO,比如网络调用或文件系统操作,这个版本将是一个很大的优化。原因是*而不是*CPU 绑定函数的优化是 [Python GIL](https://python.land/python-concurrency/the-python-gil) !
|
||
|
||
如果 Python 没有 GIL,速度会快得多。然而,尽管有 80 个线程,它的运行速度和基线差不多。实际上,基线甚至更快,因为它没有线程创建和线程间切换的所有开销。
|
||
|
||
Thank you for reading my tutorials. I write these in my free time, and it requires a lot of time and effort. I use ads to keep writing these *free* articles, I hope you understand! **Support me by disabling your adblocker on my website** or, alternatively, **[buy me some coffee](https://www.buymeacoffee.com/pythonland)**. It's much appreciated and allows me to keep working on this site!
|
||
|
||
## 一个 IO 绑定的 Python 线程示例
|
||
|
||
这是工作中的 GIL。每个线程轮流运行,而不是同时运行。为了证明这一点,如果 heavy 是一个 I/O 绑定的函数,这将会给我们带来巨大的速度提升,我们将创建一个小测试!我们可以使用`time.sleep()`来模拟 I/O 绑定软件。睡眠与阻塞 IO 有着相同的效果:它允许 CPU 做其他事情,并在特定时间过后返回。
|
||
|
||
我在下一段代码中修改了 heavy 函数:
|
||
|
||
```py
|
||
import threading
|
||
import time
|
||
|
||
# An I/O intensive calculation.
|
||
# We simulate it with sleep.
|
||
def heavy(n, myid):
|
||
time.sleep(2)
|
||
print(myid, "is done")
|
||
|
||
def threaded(n):
|
||
threads = []
|
||
|
||
for i in range(n):
|
||
t = threading.Thread(target=heavy, args=(500,i,))
|
||
threads.append(t)
|
||
t.start()
|
||
|
||
for t in threads:
|
||
t.join()
|
||
|
||
if __name__ == "__main__":
|
||
start = time.time()
|
||
threaded(80)
|
||
end = time.time()
|
||
print("Took: ", end - start)
|
||
```
|
||
|
||
即使我们有 80 个 Python 线程都休眠了两秒钟,这段代码仍然在两秒多一点的时间内完成。当休眠时,Python 线程库可以调度其他线程运行。太棒了。
|
||
|
||
## 继续学习
|
||
|
||
如果你想了解更多关于 Python 线程的知识,请务必阅读官方文档。您可能很好奇我们是否以及如何优化 CPU 受限的代码。这正是我们将在下一篇关于 [Python 多处理](https://python.land/python-concurrency/python-multiprocessing)的文章中发现的。 |