Python 多线程之threading 模块的使用


Posted in Python onApril 14, 2021

简介

Python 通过 _thread 和 threading 模块提供了对多线程的支持,threading 模块兼具了 _thread 模块的现有功能,又扩展了一些新的功能,具有十分丰富的线程操作功能

创建线程

使用 threading 模块创建线程通常有两种方式:

1)使用 threading 模块中 Thread 类的构造器创建线程,即直接对类 threading.Thread 进行实例化,并调用实例化对象的 start 方法创建线程;

2)继承 threading 模块中的 Thread 类创建线程类,即用 threading.Thread 派生出一个新的子类,将新建类实例化,并调用其 start 方法创建线程。

构造器方式

调用 threading.Thread 类的如下构造器创建线程:

threading.Thread(group=None, target=None, name=None, args=(), kwargs={}, *, daemon=None)

group:指定该线程所属的线程组,目前该参数还未实现,为了日后扩展 ThreadGroup 类实现而保留。
target:用于 run() 方法调用的可调用对象,默认是 None,表示不需要调用任何方法。
args:是用于调用目标函数的参数元组,默认是 ()。
kwargs:是用于调用目标函数的关键字参数字典,默认是 {}。
daemon:如果 daemon 不是 None,线程将被显式的设置为守护模式,不管该线程是否是守护模式,如果是 None (默认值),线程将继承当前线程的守护模式属性。
import time
import threading

def work(num):
    print('线程名称:',threading.current_thread().getName(),'参数:',num,'开始时间:',time.strftime('%Y-%m-%d %H:%M:%S'))

if __name__ == '__main__':
    print('主线程开始时间:',time.strftime('%Y-%m-%d %H:%M:%S'))
    
    t1 = threading.Thread(target=work,args=(3,))
    t2 = threading.Thread(target=work,args=(2,))
    t3 = threading.Thread(target=work,args=(1,))
    
    t1.start()
    t2.start()
    t3.start()
    
    t1.join()
    t2.join()
    t3.join()
    
    print('主线程结束时间:', time.strftime('%Y-%m-%d %H:%M:%S'))

上述示例中实例化了三个 Thread 类的实例,并向任务函数传递不同的参数,start 方法开启线程,join 方法阻塞主线程,等待当前线程运行结束。

继承方式

通过继承的方式创建线程包括如下步骤:1)定义 Thread 类的子类,并重写该类的 run 方法;2)创建 Thread 子类的实例,即创建线程对象;3)调用线程对象的 start 方法来启动线程。示例如下:

import time
import threading

class MyThread(threading.Thread):
    
    def __init__(self,num):
        super().__init__()
        self.num = num
    
    def run(self):
        print('线程名称:', threading.current_thread().getName(), '参数:', self.num, '开始时间:', time.strftime('%Y-%m-%d %H:%M:%S'))

if __name__ == '__main__':
   
     print('主线程开始时间:',time.strftime('%Y-%m-%d %H:%M:%S'))
    
    t1 = MyThread(3)
    t2 = MyThread(2)
    t3 = MyThread(1)
   
     t1.start()
    t2.start()
    t3.start()
    
    t1.join()
    t2.join()
    t3.join()
    
    print('主线程结束时间:', time.strftime('%Y-%m-%d %H:%M:%S'))

上述示例中自定义了线程类 MyThread,继承了 threading.Thread,并重写了 __init__ 方法和 run 方法。

守护线程

守护线程(也称后台线程)是在后台运行的,它的任务是为其他线程提供服务,如 Python 解释器的垃圾回收线程就是守护线程。如果所有的前台线程都死亡了,守护线程也会自动死亡。来看个例子:

# 不设置守护线程
import threading

def work(num):
    for i in range(num):
        print(threading.current_thread().name + "  " + str(i))

t = threading.Thread(target=work, args=(10,), name='守护线程')
t.start()

for i in range(10):
    pass
# 设置守护线程
import threading

def work(num):
    for i in range(num):
        print(threading.current_thread().name + "  " + str(i))

t = threading.Thread(target=work, args=(10,), name='守护线程')
t.daemon = True
t.start()

for i in range(10):
    pass

上述示例直观的说明了当前台线程结束,守护线程也会自动结束。

如果你设置一个线程为守护线程,就表示这个线程是不重要的,在进程退出的时候,不用等待这个线程退出;如果你的主线程在退出的时候,不用等待哪些子线程完成,那就设置这些线程为守护线程;如果你想等待子线程完成后再退出,那就什么都不用做,或者显示地将  daemon 属性设置为 false。

线程本地数据

Python 的 threading 模块提供了 local 方法,该方法返回得到一个全局对象,不同线程使用这个对象存储的数据,其它线程是不可见的(本质上就是不同的线程使用这个对象时为其创建一个独立的字典)。来看个示例:

# 不使用 threading.local
import threading
import time

num = 0

def work():
    global num
    
    for i in range(10):
        num += 1
        
    print(threading.current_thread().getName(), num)
    time.sleep(0.0001)
    
for i in range(5):
    threading.Thread(target=work).start()

上面示例中 num 是全局变量,变成了公共资源,通过输出结果,我们发现子线程之间的计算结果出现了互相干扰的情况。

# 使用 threading.local
num = threading.local()

def work():
    num.x = 0
    
    for i in range(10):
        num.x += 1
    
    print(threading.current_thread().getName(), num.x)
    time.sleep(0.0001)

for i in range(5):
    threading.Thread(target=work).start()

使用 threading.local 的示例中,num 是全局变量,但每个线程定义的属性 num.x 是各自线程独有的,其它线程是不可见的,因此每个线程的计算结果未出现相互干扰的情况。

定时器

threading 模块提供了 Timer 类实现定时器功能,来看个例子:

# 单次执行
from threading import Timer

def work():
    print("Hello Python")
    
# 5 秒后执行 work 方法
t = Timer(5, work)
t.start()

Timer 只能控制函数在指定的时间内执行一次,如果我们需要多次重复执行,需要再进行一次调度,想要取消调度时可以使用 Timer 的 cancel 方法。来看个例子:

# 重复执行
count = 0

def work():
    print('当前时间:', time.strftime('%Y-%m-%d %H:%M:%S'))
    global t, count
    count += 1
    # 如果 count 小于 5,开始下一次调度
    if count < 5:
        t = Timer(1, work)
        t.start()

# 指定 2 秒后执行 work 方法
t = Timer(2, work)
t.start()

以上就是Python 多线程之threading 模块的使用的详细内容,更多关于python threading的使用的资料请关注三水点靠木其它相关文章!

Python 相关文章推荐
python数据结构之二叉树的建立实例
Apr 29 Python
python中xrange用法分析
Apr 15 Python
使用Python读写文本文件及编写简单的文本编辑器
Mar 11 Python
Pandas 数据处理,数据清洗详解
Jul 10 Python
python实现栅栏加解密 支持密钥加密
Mar 20 Python
基于python3 pyQt5 QtDesignner实现窗口化猜数字游戏功能
Jul 15 Python
python 实现图片上传接口开发 并生成可以访问的图片url
Dec 18 Python
Django模板标签中url使用详解(url跳转到指定页面)
Mar 19 Python
详解Python中Pyyaml模块的使用
Oct 08 Python
scrapy头部修改的方法详解
Dec 06 Python
python多线程方法详解
Jan 18 Python
python和Appium的移动端多设备自动化测试框架
Apr 26 Python
教你如何用python开发一款数字推盘小游戏
深度学习详解之初试机器学习
正确的理解和使用Django信号(Signals)
Apr 14 #Python
编写python程序的90条建议
Apr 14 #Python
Python基础知识之变量的详解
理解深度学习之深度学习简介
Apr 14 #Python
python基于scrapy爬取京东笔记本电脑数据并进行简单处理和分析
You might like
回答PHPCHINA上的几个问题:URL映射
2007/02/14 PHP
CI框架中zip类应用示例
2014/06/17 PHP
完美解决thinkphp验证码出错无法显示的方法
2014/12/09 PHP
PHP有序表查找之插值查找算法示例
2018/02/10 PHP
IE JS编程需注意的内存释放问题
2009/06/23 Javascript
jQuery调用WebService的实现代码
2011/06/19 Javascript
javascript 全选与全取消功能的实现代码
2012/12/23 Javascript
js中方法重载如何实现?以及函数的参数问题
2013/08/01 Javascript
jquery中交替点击事件toggle方法的使用示例
2013/12/08 Javascript
JavaScript框架是什么?怎样才能叫做框架?
2015/07/01 Javascript
jQuery实现选项联动轮播效果【附实例】
2016/04/19 Javascript
javaScript事件学习小结(四)event的公共成员(属性和方法)
2016/06/09 Javascript
AngularJS实现给动态生成的元素绑定事件的方法
2016/12/14 Javascript
vue 刷新之后 嵌套路由不变 重新渲染页面的方法
2018/09/13 Javascript
vue+element实现打印页面功能
2019/05/20 Javascript
vue实现吸顶、锚点和滚动高亮按钮效果
2019/10/21 Javascript
[04:52]第二届DOTA2亚洲邀请赛主赛事第一天比赛集锦:OG娜迦海妖放大配合谜团大中3人
2017/04/02 DOTA
Python修改Excel数据的实例代码
2013/11/01 Python
Python开发如何在ubuntu 15.10 上配置vim
2016/01/25 Python
Python基于PyGraphics包实现图片截取功能的方法
2017/12/21 Python
python实战教程之自动扫雷
2018/07/13 Python
Python Flask框架模板操作实例分析
2019/05/03 Python
python GUI库图形界面开发之PyQt5图片显示控件QPixmap详细使用方法与实例
2020/02/27 Python
Python爬取YY评级分数并保存数据实现过程解析
2020/06/01 Python
python中把元组转换为namedtuple方法
2020/12/09 Python
使用OpenCV实现人脸图像卡通化的示例代码
2021/01/15 Python
法国和欧洲海边和滑雪度假:Pierre & Vacances
2017/01/04 全球购物
Parfumdreams芬兰:购买香水和化妆品
2021/02/13 全球购物
纪念建党演讲稿范文
2014/01/13 职场文书
党员学习党的群众路线思想汇报(5篇)
2014/09/10 职场文书
2014法制宣传日活动总结范文
2014/11/01 职场文书
爱心助学感谢信
2015/01/21 职场文书
2015年前台文员工作总结
2015/05/18 职场文书
投资申请报告
2015/05/19 职场文书
公务员学习中国梦心得体会
2016/01/05 职场文书
Python数据可视化之用Matplotlib绘制常用图形
2021/06/03 Python