一,使用Threading模块创建线程
1,引入threading模块
import threading
2,通过threading.Thread引用子线程函数
t2 = threading.thread(target=Thread2)
3,启动子线程start()
t2.start()
4,案例演示:
import time
import threading
def Thread1(): # 子线程2
for i in range(5):
print("你好我是1号线程")
time.sleep(1)
def Thread2(): # 子线程2
for i in range(5):
print("我是二号线程")
time.sleep(1)
def main(): # 主线程
t1 = threading.Thread(target=Thread1)
t2 = threading.Thread(target=Thread2)
t1.start()
t2.start()
if __name__ == "__main__":
main()
~
可以看到两个函数同时运行
二,查看正在运行的线程
通过threading.enumerate()
方法查看正在运行的线程
因为执行这个方法时会查看一次,这时候子线程还没启动,所以需要循环查看
t1 = threading.Thread(target=Thread1)
t2 = threading.Thread(target=Thread2)
t1.start()
t2.start()
while True:
print(threading.enumerate())
if len(threading.enumerate())<=1:
break
Python中主线程会默认等到所有的子线程结束完后再结束,当主线程死后,所有的子线程都会死
三,通过继承Thread类创建线程
适用于代码长的,逻辑性比较强的线程,上面我们是通过引用函数来实现线程,同时我们也可以通过类来实现
1,定义一个类,继承于Thread,并重写run方法
import threading
import time
class MyThread(threading.Thread):
def run(self):
for i in range(5):
print("我是子线程")
time.sleep(1)
2,创建该类的实例化对象,并执行start方法,该方法会自动执行run方法的内容
t1 = MyThread()
t1.start()
3,案例演示:
import threading
import time
class MyThread(threading.Thread):
def run(self):
for i in range(5):
print("我是子线程")
time.sleep(1)
def main():
t1 = MyThread()
t1.start()
for i in range(5):
print("我是主线程")
time.sleep(1)
if __name__ == "__main__":
main()
四,多线程共享全局变量
1,使用asgs参数
因为多线程也相当于函数,所以多线程之间共享全局变量可以通过global
获取全局变量
同时也可以通过args
参数传入要共享的元祖参数
t2 = threading.Thread(target=Thread2,args=(g_number,)) #注意是元祖类型,要有逗号
def Thread2(temp) #temp接收传入的元祖数据
temp.appen(33)
这样在子线程中也可以更改主线程的数据
但是这样可能会造成资源竞争使结果不准确
2,使用互斥锁解决资源竞争问题
需要通过创建互斥锁
当一个线程在操作数据时,锁上,其他线程不能使用
mutex.acquire()
上锁,如果该数据已上锁,会堵塞,直到锁被解开后再上锁
mutex.release()
解锁
在实际操作中,在数据使用前上锁,使用后解锁
def Thread1(temp): # 子线程2
for i in range(5):
print("你好我是1号线程")
time.sleep(1)
mutex.acquire() #上锁
temp.append(3)
mutex.release() #解锁