我们知道工人都是同时在工厂工作,复制各自的工作的。他们就是一个一个独立运行的单位!
线程也是类似这样的一个独立的运行单位,多线程,就是多个独立的运行单位,同时执行同样的事情。
简单这样理解,后面会进行对比。
threading.Thread
类是Python
中的线程类,它封装了线程的信息和一些同用的方法。
线程有状态,拿工人一天的状态来比喻很合适,早上上班,然后工作,有时候需要停下来休息,最后下班。
运行下面的代码看看:
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
我们可以使用线程来调用。下面学委写了一个带参数的函数。 通过线程调用业务函数的时候指定:
def dianzan_guanzhu(name): #省略一些代码 mythread = threading.Thread(target=dianzan_guanzhu, kwargs={"name": "python萌新"})
好下面,编写全部代码,使用线程来点赞,和直接调用
我们看看下面的代码:
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脚本,运行代码的时候,本身是在一个主线程中的。
只是之前一直没解除线程概念,没写多线程程序,没有感知到这事情。
从现在开始,你要清楚知道:每个程序运行都有一个主线程。
回到结果,两个线程先后依次调用通过函数:
我们先把线程的基础知识搞懂。
Thread
类来做, target
参数用来绑定业务函数。启动线程用start函数。