前面文章写了很多,都是比较基础的。
这篇开始我们将进入中级编程。处理更加复杂事情。比如本文的线程,咱们先从基础知识入手!
什么是线程?
我们知道工人都是同时在工厂工作,复制各自的工作的。他们就是一个一个独立运行的单位!
线程也是类似这样的一个独立的运行单位,多线程,就是多个独立的运行单位,同时执行同样的事情。
简单这样理解,后面会进行对比。
threading.Thread 类是Python中的线程类,它封装了线程的信息和一些同用的方法。
线程有状态,拿工人一天的状态来比喻很合适,早上上班,然后工作,有时候需要停下来休息,最后下班。
复制运行下面的代码看看:
#!/usr/bin/env python # -*- coding: utf-8 -*- # @Time : 2021/11/21 12:02 上午 # @Author : LeiXueWei # @CSDN/Juejin/Wechat: 雷学委 # @XueWeiTag: CodingDemo # @File : __init__.py.py # @Project : hello import threading mythread = threading.Thread() print("mythread:", mythread) print("is_alive:", mythread.is_alive()) mythread.start() print("mythread:", mythread) print("is_alive:", mythread.is_alive())
下面是运行结果:
建议读者先运行一下。
再来解释线程的代码
上面我们使用了threading这个库,然后创建Thread类的对象实例,赋值给mythread变量。
接着打印了对象和线程对象的一个函数is_alive()是否活跃状态。
两次都是False(这个后面再说)
但是第二次我们看到线程对象打印出来变成‘stopped’.
也就是说我们跑完了start函数(该函数为线程启动函数)之后,线程就进入stopped状态了。
上面那个就是线程,可是貌似啥也没做,我们下面让它做点事情呗。
线程触发业务函数,线程调用业务函数
比如这次的业务是:关注和点赞。
def dianzan_guanzhu(): now = datetime.datetime.now() #初始化时间变量 name = "python萌新" print("%s name:%s" % (now, name)) #第一次打印时间和粉丝名字 time.sleep(1) result = "好棒!" + name + " 关注雷学委,白嫖了好多知识和开发经验!" print("%s result:%s" % (now, result)) #第二次打印时间和粉丝活动 return result
我们可以使用线程来调用。下面学委写了一个带参数的函数。 通过线程调用业务函数的时候指定:
- target:设置为即将被调用的函数
- kwargs: 如果有参数,直接通过传递一个k-v dict即可。
def dianzan_guanzhu(name): #省略一些代码 mythread = threading.Thread(target=dianzan_guanzhu, kwargs={"name": "python萌新"})
好下面,编写全部代码,使用线程来点赞,和直接调用点赞。
我们看看下面的代码:
#!/usr/bin/env python # -*- coding: utf-8 -*- # @Time : 2021/11/21 12:02 上午 # @Author : LeiXueWei # @CSDN/Juejin/Wechat: 雷学委 # @XueWeiTag: CodingDemo # @File : __init__.py.py # @Project : hello import threading import datetime import time """学委定义了一个关注函数""" def dianzan_guanzhu(): now = datetime.datetime.now() name = "python萌新" print("%s name:%s" % (now, name)) time.sleep(1) result = "好棒!" + name + " 关注雷学委,学到了好多知识和开发经验!" print("%s result:%s" % (now, result)) return result mythread = threading.Thread(target=dianzan_guanzhu) print("mythread:", mythread) print("is_alive:", mythread.is_alive()) mythread.start() print("mythread:", mythread) print("is_alive:", mythread.is_alive()) dianzan_guanzhu() print("is_alive:", mythread.is_alive())
直接复制运行,这里我们这个dianzan_guanzhu函数被调用了两次
第一次是mythread.start函数。
第二次是我们直接脱离线程调用dianzan_guanzhu函数。
下面是运行结果:
好像没啥的样子。
再看一次,注意关注每次打印的时间,输入的时间好像错乱了?没错,不是眼花,是正确运行结果。
因为进入dianzan_guanzhu函数之后,初始化了now变量,这个时间固定了。
但是在线程外面也调用dianzan_guanzhu函数,所以这里是:两个线程在同时做同样的事情。
多了一个线程是哪个?
这里补充一下,我们写python脚本,运行代码的时候,本身是在一个主线程中的。
只是之前一直没解除线程概念,没写多线程程序,没有感知到这事情。
从现在开始,你要清楚知道:每个程序运行都有一个主线程。
回到结果,两个线程先后依次调用通过函数:
首先,先后依次打印第一行输出。
分开休眠了一秒(sleep(1))。
最后,先后依次打印第二行输出。
总结
我们先把线程的基础知识搞懂。
每个程序运行过程中至少有一个主线程
需要启动更多线程使用Thread类来做, target参数用来绑定业务函数。启动线程用start函数。
下一节再分享线程的更多知识。