一、多线程:
直接使用threading模块的Thread类来创建线程,多个线程可以共享进程的内存空间,Python的多线程并不能发挥CPU的多核特性。
二、创建多线程:
import threading
import win32api
第一种用函数创建多线程,但是需要处理让脚本主线程不死
第二种是基于类继承创建多线程
第三种:(不推荐使用)
threading.Thread(target=show,args=(i,)).start() # 切记这里的args是一个元组
threading.Thread(target=show,args=(i,)).start()
创建五个多线程求和(使用函数创建多线程),线程冲突,5个线程同时抢夺num的资源,导致最后结果错误
import _thread
NUM = 0
def A():
global NUM
for i in range(10000000):
NUM += 1
print(NUM)
for i in range(5): # 这是子线程, 同时执行5次
_thread.start_new_thread(A,()) # 前面是执行函数,后面是一个元组,可以不写前提是函数没有形参
while 1: # 在这里加入死循环是为了脚本主线程不死,子线程才能运行
pass
执行结果:
11781908
12025580
13214742
14260177
14316790
使用类创建多线程
NUM = 0
import threading
class WJL(threading.Thread): # 继承threading.Thread类
def __init__(self):
threading.Thread.__init__(self)
#self.NUM = 0
def run(self): # 重写threading.Thread类中的run函数
global NUM
for _ in range(1000):
NUM += 1
print(NUM)
if __name__ == "__main__":
for i in range(5):
t=WJL() # 初始化
t.start()
while 1:
pass
执行结果:
1000
2000
3000
4000
5000
创建锁(必须得释放锁)可以解决线程冲突
import threading
import random
mutex = threading.Lock() # 创建一个锁,threading.Lock()是一个类
NUM = 0
class Mythread(threading.Thread):
def run(self):
global NUM
if mutex.acquire(1): # 如果锁成功,那么线程继续干活,如果锁失败,下面的线程一直等待锁成功,1,代表独占
for i in range(100):
NUM += 1
mutex.release() # 释放锁
print(NUM)
mythread =[]
for i in range(3):
t = Mythread()
t.start()
mythread.append(t)
执行结果:
100
200
300
game over
类线程的乱序风格,会输出五个白框
import threading
import win32api
class Mythread(threading.Thread): # 继承threading.Thread类
def __init__(self, num):
threading.Thread.__init__(self) # 父类初始化
self.num = num
def run(self): # 定义函数
win32api.MessageBox(0, "王璐~~~" + str(self.num), 'wjl', 0)
print(self.getName()) # 获取线程名
Mythd = []
for i in range(5):
t = Mythread(i) # 初始化
print(i)
t.start() # 开启
Mythd.append(t) # 将乱序线程(同时抢夺run这个函数)加入列表
for j in Mythd:
# 这里与顺序不同,上面显示所有的线程都加入Mthd列表(所以一次性跳出5个窗口,但是主线程还没死,因为有join卡住)。
# j是线程
j.join() # 这里主线程同时等待所有线程都执行完毕,才执行“game over”
print("game over")
执行结果:
0
1
2
3
4
Thread-4
Thread-1
Thread-2
Thread-3
Thread-5
game over
多线程的通信,使用wait 等待事件,等待set消息
import threading
import time
def goevent():
e = threading.Event() # 事件
def go():
e.wait() # 等待事件,线程卡顿,等待set消息
print("go")
threading.Thread(target=go).start() # 需要创建一个线程
return e
t = goevent()
执行结果:go
使用threading.Semaphore(2)控制最大线程数,当超过限制数的时候就不执行,即最多限制数个线程可同时执行
import threading
import time
sem = threading.Semaphore(2) # 限制最大线程数为2个
def gothread():
with sem: # 锁定数量
for i in range(10):
print(threading.current_thread().name, i) # 打印线程名字
time.sleep(1)
for i in range(5):
threading.Thread(target=gothread).start() # 乱序执行多线程,就可以考虑为有些cpu牛逼些能够执行快一点
执行结果:
Thread-1 0
Thread-2 0
Thread-2 1
Thread-1 1
Thread-1 2
Thread-2 2
Thread-1 3
Thread-2 3
Thread-1 4
Thread-2 4
Thread-1 5
Thread-2 5
使用threading.Barrier(2)控制线程数量a,即只有数量达到a才可以执行多线程,否则一直在等待
import threading
# 凑出线程数量,也就是说一定要至少凑成两个才能执行
# 换而言之,也就是说只有创建线程数是2,或者2的倍数才能全部执行
bar = threading.Barrier(2)
def sever():
print(threading.current_thread().name,"start")
bar.wait()
print(threading.current_thread().name,"end")
for i in range(3):
threading.Thread(target=sever).start()
执行结果:
Thread-1 start
Thread-2 start
Thread-2 end
Thread-1 end
Thread-3 start