浅谈 Python 中的多线程。

本文作者:Rocky0249

公众号:Python空间

00.写在之前

大家好,我是 Rocky0429,今天我来写一下 Python 中的多线程。在正式开始之前,我先用比较通俗的语言给大家介绍几个比较重要的概念。

首先是「并发编程」。「并发」其实在我们的生活中随处可见,比如我们去银行存钱,银行如果只有一个窗口并且办业务的人又比较多,那么肯定就是排成一个长长的队伍,这样的体验对我们来说肯定是非常差的。那么该如何解决这个问题呢?那就是多开几个窗口,把人流分散开,这样就减短了我们队伍的长度,减少整体排队的时间。

上面是我们显示生活中遇到的问题,其实在计算机中我们也会遇到这样的问题,那么我们是怎么解决的呢?其实是这样,每次我们运行一个 Python 程序,这个运行中的程序我们称它为「进程」,如果我们想让它快一点,能够像我们上面例子中多开几个窗口并发解决问题一样,我们就要在进程里引入一个更小的东西,那就是「线程」。

我来举一个具体的例子,比如我们每天都会用的微信,每次运行它的时候会产生一个进程,估计大家都碰到过这种情况,就是你在和别人开视频的时候,另外有一个人给你发消息,我们都知道这个时候可以把视频的窗口缩小然后回复另一个人的消息,能完成这样的操作,其实就是微信里的多个线程帮助我们完成了这件事。

在编写 Python 程序的时候我们也会遇到这种“同时”的需求,同时有大量的请求过来,要我们同时对它们进行处理,那么这个处理的方法,就是「多线程」编程。

01.创建「线程」

Python 的标准库中自带了多线程相关的模块,使在 python 中创建线程成了一件很简单的事。与线程相关的模块一共有两个:thread 和 threading。一般情况下我们只需要 threading 即可。

下面我来写一个简单的使用多线程的例子:

import threading
def func():    print('Hello World')
def main():    for i in range(4):        t = threading.Thread(target=func)        t.start()
if __name__ == '__main__':    main()

上面的代码中,我定义了一个 func 函数,然后在 main 函数中通过 for 循环创建了 4 个线程,然后通过将 target = func 的方式去告诉线程执行 func 函数,一切就绪后调用线程的 start 方法运行线程。结果如下:

Hello WorldHello WorldHello WorldHello World

这个结果看起来和我们直接用 for 循环打印四次 Hello World 没什么区别,其实区别还是有的,就是肉眼看不出来而已,下面我来改造一下上面的程序:

import threadingimport time
def func():    print('Hello World')    time.sleep(1)
def main():    for i in range(4):        t = threading.Thread(target=func)        t.start()
if __name__ == '__main__':    main()

上面我加了 time.sleep(1),如果只是用 for 循环的话,这个程序至少得运行 4 秒,但是由于我们用的是线程并发运行,其实整个程序只需要花费 1 秒多就可以运行完毕,你可以自行尝试一下,可以 sleep 的时间长点自行体验一下。

当然了,如果你自己不乐意动手,作为关爱读者成长协会的会长,我这还有一个好的办法,且待我再改造一下:

import threadingimport timefrom threading import current_thread
def func():    print(current_thread().getName(),'start')    print('Hello World')    time.sleep(1)    print(current_thread().getName(), 'end')
def main():    for i in range(4):        t = threading.Thread(target=func)        t.start()
if __name__ == '__main__':    main()

上面的改造中引用了 current_thread,对当前运行状态进行一个显示,你可以很好的看到线程在运行中的一些过程,运行结果如下所示:

Thread-1 startHello WorldThread-2 startHello WorldThread-3 startHello WorldThread-4 startHello WorldThread-1 endThread-4 endThread-3 endThread-2 end

02.线程传参

在上面创建线程的例子其实是过于简单了,在我们实际的编程中给程序传递参数是必不可少的,下面我在之前例子的基础上,写一个传递参数的例子:

import threading
def func(cnt, name):    for i in range(cnt):        print('Hello {}'.format(name))
def main():    names = ['Rocky', 'leey', 'cp3', 'chen']    for i in range(4):        t = threading.Thread(target=func, args=(10, names[i]))        t.start()
if __name__ == '__main__':    main()

上面的程序中,我让 func 接受了两个参数,在 main 函数中定义了一个 names 的列表,之后在创建线程的时候将 names 中的元素传递给不同的线程。由上可以看出在 Python 中线程传递参数也是一件很简单的事,传递的参数都是调用 args,通过元组的形式进行。

03.写在之后

其实很多人认为 Python 的多线程是一个相当“鸡肋”的东西,因为标准的 Python 系统中使用了 GIL(全局解释器锁),它的作用是避免 Python 解释器中的线程问题,这样造成了在任意时刻只有一个线程在执行 Python 代码,这样就“糟蹋”了计算机「多核」的特性。

诚然,“糟蹋”了多核,这样对 CPU 密集型的程序来说,Python 多线程确实没有什么提升,反而会更慢,但我们的程序其实也不是无时无刻在“动弹”的,它们也要等待资源的下载,等待文件的读写,等待用户的输入等等等等,这类操作我们统一称为 I/O 操作,对于这类,才是真正显示 Python 多线程能力的时候。所以,也不是太“鸡肋”嘛。

本文分享自微信公众号 - 小詹学Python(xiaoxiaozhantongxue)

原文出处及转载信息见文内详细说明,如有侵权,请联系 yunjia_community@tencent.com 删除。

原始发表时间:2019-03-22

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏量子位

微软VS Code已原生支持Jupyter笔记本,再也不用打开网页调试运行了

本月,微软给VS Code加入了一项令人感到惊喜的功能:直接在编辑器中运行调试Jupyter Notebook,而无需任何第三方插件。

30040
来自专栏磐创AI技术团队的专栏

PyTorch&TensorFlow跑分对决:哪个平台运行NLP模型推理更快

开源社区的支持度、上手的难易度都是重要的参考。还有人说:学术界用PyTorch,工业界用TensorFlow。

7120
来自专栏猪圈子

Python学习曲线

经历长达近一个月的资源筛选过程终于结束,总共1.5T百度网盘的资源经过:去重、筛选、整理、归档之后一份粗略的Python学习曲线资源已经成型,虽然中间经历了很多...

17410
来自专栏Python工程师

Python-科学计算-pandas-01-df获取部分数据

系统:Windows 7 语言版本:Anaconda3-4.3.0.1-Windows-x86_64 编辑器:pycharm-community-2016.3....

8330
来自专栏量子位

英伟达小姐姐的Python隐藏技巧合集,推特2400赞,代码可以直接跑

常常发资源的英伟达工程师小姐姐Chip Huyen,又发射了一套Python隐藏功能合集。

8430
来自专栏中科院渣渣博肆僧一枚

tf.compat

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。 ...

4930
来自专栏生信技能树

爬虫那么危险,干嘛不直接基因数据库下载文件呢?

问了具体后,才知道原来是ncbi上的信息,相当于在ncbi上在gene库中查找,然后爬取目标信息。如下:

17830
来自专栏华章科技

Python 3.8已正式发布,重要新功能都在这里了

导读:最新版本的Python发布了!今年夏天,Python 3.8发布beta版本,在2019年10月14日,第一个正式版本已准备就绪。现在,我们都可以开始使用...

33240
来自专栏测试游记

测试开发进阶(二十八)

进入 get_object_or_404可以看到一个解包,这样就拿到了查询集中 id=1的内容

6030
来自专栏Datawhale专栏

大数据处理实践!手把手实现PySpark机器学习项目-回归算法

PySpark作为工业界常用于处理大数据以及分布式计算的工具,特别是在算法建模时起到了非常大的作用。PySpark如何建模呢?这篇文章手把手带你入门PySpa...

11270

扫码关注云+社区

领取腾讯云代金券

年度创作总结 领取年终奖励