多线程
在Python早期的版本中就引入了thread模块(现在名为_thread)来实现多线程编程,然而该模块过于底层,而且很多功能都没有提供,因此目前的多线程开发我们推荐使用threading模块,该模块对多线程编程提供了更好的面向对象的封装。
import _thread # 多线程
import win32api
def show(i):
# 0 代表系统,你最帅代表内容,来自。。。。。代表标题,0代表窗口类型0,1,2,3
mystr = win32api.MessageBox(0,"你是帅哥吗?","来自火星的的逗比",3)
for i in range(5): # 这是小弟线程
_thread.start_new_thread(show,(i,)) # 前面是执行函数,后面是一个元组,可以不写前提是函数没有形参
while True: # 在这里加入死循环是为了脚本主线程不死,小弟线程才能运行
pass
多线程速度
import _thread
import time
def go():
for i in range(5):
print(i,"-------")
time.sleep(1)
for i in range(5): # 同时执行5次
_thread.start_new_thread(go,())
for j in range(6): # 让主线程卡顿6秒
time.sleep(1)
print("over")
======================
0 -------
0 -------
0 -------
0 -------
0 -------
1 -------
1 -------
1 -------
1 -------
1 -------
2 -------
2 -------
2 -------
2 -------
2 -------
3 -------
3 -------
3 -------
3 -------
3 -------
4 -------
4 -------
4 -------
4 -------
4 -------
over
import threading
class Hooper(threading.Thread):
def __init__(self):
threading.Thread.__init__(self)
self.NUM = 0
def run(self):
for _ in range(1000):
self.NUM += 1
print(self.NUM)
if __name__ == "__main__":
for i in range(5):
t = Hooper()
t.start()
while 1:
pass
======================
1000
1000
1000
1000
1000
两个线程输出随机数
import threading
import random
class Hooper(threading.Thread):
def __init__(self,lock):
threading.Thread.__init__(self)
self.lock = lock
self.list_ = []
def run(self):
for i in range(50):
res = random.randrange(1000,9999)
print(res)
self.list_.append(res)
with self.lock:
self.write(self.list_)
def write(self,num):
b = [str(x) + '\n' for x in num]
b = ''.join(b)
with open('res.txt',mode = 'a') as file:
file.write(b)
if __name__ == "__main__":
ts = []
lock = threading.Lock()
for i in range(2):
t = Hooper(lock)
t.start()
ts.append(t)
for t in ts:
t.join()
print('Over')
线程冲突
import _thread
num = 0
def add():
for _ in range(1000000):
global num
num += 1
print(num)
'''
for j in range(5):
add()
'''
for i in range(5):
_thread.start_new_thread(add,())
# 这里就是线程冲突,5个线程同时抢夺num的资源,导致最后结果错误
'''
1144840
1488805
1671079
1700819
1920182
'''
while True: # 防止主线程不死
pass
基于类解决类的冲突
import threading
num = 0
mutex = threading.Lock() # 创建一个锁,threading.Lock()是一个类
class Myhtread(threading.Thread):
def run(self):
global num
if mutex.acquire(1): # 如果锁成功,那么线程继续干活,如果锁失败,下面的线程一直等待锁成功,1,代表独占
for i in range(1000): # 数字小的时候还是不会产生线程冲突的
num += 1
mutex.release() # 释放锁,一定切记
print(num)
mythread = []
for i in range(5):
t = Myhtread()
t.start()
mythread.append(t)
for thread in mythread:
thread.join() # 或者直接将thread.join()加入for i in range(5),也能解决线程冲突,但是貌似就变成单线程了
print("game over")
======================
1000
2000
3000
4000
5000
game over
死锁
死锁是指两个或两个以上的进程在执行过程中,由于竞争资源或者由于彼此通信而造成的一种阻塞的现象,若无外力作用,它们都将无法推进下去。此时称系统处于死锁状态或系统产生了死锁,这些永远在互相等待的进程称为死锁进程。
import threading
import time
boymutex = threading.Lock() # 创建一个锁
girlmutex = threading.Lock() # 创建一个锁
class boy(threading.Thread):
def run(self):
if boymutex.acquire(1): # 锁定成功就继续执行,锁定不成功,就一直等待
print(self.name + "boy say i am sorry up")
# time.sleep(3) # 时间过短的话也可以并发执行,不会锁死
if girlmutex.acquire(1): # 锁定不成功,因为下面已经锁定
print(self.name + "boy say i am sorry down")
girlmutex.release()
boymutex.release()
class girl(threading.Thread):
def run(self):
if girlmutex.acquire(1): # 锁定成功就继续执行,锁定不成功,就一直等待
print(self.name + "girl say i am sorry up")
# time.sleep(3)
if boymutex.acquire(1): # 锁定不成功,同理上面已经锁定一直等待
print(self.name + "girl say i am sorry down")
boymutex.release()
girlmutex.release()
# 开启两个线程
# boy1 = boy() # Thread-1boy 第一个线程
# boy1.start()
# girl1 = girl()
# girl1.start()
'''
这种例子时间过短是无法很好的产生死锁
for i in range(10):
Mythread1().start()
Mythread2().start()
'''
for i in range(1000):
boy().start()
girl().start()
==================
Thread-1boy say i am sorry up
Thread-1boy say i am sorry down
Thread-2girl say i am sorry up
Thread-3boy say i am sorry up
创建多线程
第一种用函数创建多线程,但是需要处理让脚本主线程不死
import threading
import win32api
class Mythread(threading.Thread): # 继承threading.Thread类
def run(self): # 定义函数
win32api.MessageBox(0, "hello", 'joker', 0)
Mythd = []
for i in range(5):
t = Mythread() # 初始化
print(i)
t.start() # 开启
Mythd.append(t) # 将乱序线程(同时抢夺run这个函数)加入列表
for j in Mythd:
# 这里与顺序不同,上面显示所有的线程都加入Mthd列表(所以一次性跳出5个窗口,但是主线程还没死,因为有join卡住)。
# j是线程
j.join() # 这里主线程同时等待所有线程都执行完毕,才执行“game over”
print("game over")
'''
'''
第二种是基于类继承创建多线程
import threading
import win32api
class Mythread(threading.Thread): # 继承threading.Thread类
def run(self): # 重写threading.Thread类中的run函数
win32api.MessageBox(0,"hello",'joker',0)
for i in range(5): # 同时创建5个线程
t = Mythread() # 初始化
t.start() # 开启
while True:
pass
'''
'''
def show(i):
win32api.MessageBox(0,"这是一个测试","来自Joker",0)
threading.Thread(target=show,args=(i,)).start() # 切记这里的args是一个元组
threading.Thread(target=show,args=(i,)).start()
'''
# 基于函数构造实现多线程
import threading
import win32api
def show():
win32api.MessageBox(0, "这是一个测试", "来自Joker", 0)
# target=show是线程函数,args=()是参数
threading.Thread(target=show, args=()).start()
threading.Thread(target=show, args=()).start()
线程通信event
import threading
import time
def A(e):
e.wait()
print('Hello')
def B(e):
time.sleep(3)
e.set()
if __name__ == "__main__":
e = threading.Event()
t1 = threading.Thread(target=A,args=(e,))
t2 = threading.Thread(target=B,args=(e,))
t1.start()
t2.start()
t1.join()
====================
Hello
多线程利用装饰器
import threading
import time
def deco2(times):
def deco(func):
def warp(*args,**kwargs):
e = args[0]
time.sleep(times)
e.set()
return func(*args,**kwargs)
return warp
return deco
@deco2(5)
def A(e):
e.wait()
print('Hello Word')
if __name__ == "__main__":
e = threading.Event()
t = threading.Thread(target=A,args=(e,))
t.start()
t.join()
=============================
Hello Word
加油,明天会更好的!fighting!!!