线程
- 进程相互独立,线程依赖于进程
- 线程需要抢CPU,谁先抢到谁执行
**Python中使用线程有两种方式:函数或者用类来包装线程对象。
1.函数式:调用thread模块中的start_new_thread()函数来产生新线程。
thread.start_new_thread ( function, args[, kwargs] )
2.使用Threading模块创建线程,直接从threading.Thread继承,然后重写__init__方法和run方法
**
线程冲突,5个线程同时抢夺num的资源,导致最后结果错误
import _thread
num = 0
def add():
for _ in range(1000000):
global num
num += 1
print(num)
for i in range(5):
_thread.start_new_thread(add,())
while True: # 防止主线程不死
pass
基于类实现线程
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
类线程的顺序风格
import threading
import win32api
class Mythread(threading.Thread): # 继承threading.Thread类
def run(self): # 定义函数
win32api.MessageBox(0,"hello",'joker',0)
for i in range(5):
t = Mythread() # 初始化
t.start() # 开启
t.join()
print("game over")
- start是启动线程,join是阻塞当前线程,即使得在当前线程结束时,不会退出。
类线程的乱序风格
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, "hello" + str(self.num), 'joker', 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:
j.join() # 这里主线程同时等待所有线程都执行完毕,才执行“game over”
print("game over")
基于类解决线程冲突
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")
用两个线程随机获取100个验证码,写入本地文件
import threading
import random
class Mythread (threading.Thread):
def __init__(self,lock):
threading.Thread.__init__(self)
self.lock = lock
self.list_ = []
def run(self):
for i in range(50):
num = random.randrange(1000,9999)
print(num)
self.list_.append(num)
with self.lock:
self.write(self.list_)
def write(self,res):
b = [str(x)+'\n' for x in res]
b = ''.join(b)
with open('./res.txt',mode = 'a')as file:
file.write(str(res)+'\n')
if __name__ == "__main__":
mythread = []
lock = threading.Lock()
for i in range(2):
t = Mythread(lock)
t.start()
mythread.append(t)
for t in mythread:
t.join()
print("Over")
Rlock避免单线程死锁
import threading
num = 0
mutext = threading.RLock()
class Mythreading(threading.Thread):
def run(self):
global num
if mutext.acquire(1):
num += 1
print(self.name, num)
if mutext.acquire(1):
num += 1000
mutext.release()
mutext.release()
for i in range(5): # 开启5个进程
t = Mythreading()
t.start()
threading.Semaphore(2) # 限制最大线程数为2个
threading.Barrier(2) #凑出线程数量,也就是说一定要至少凑成两个才能执行
线程通信
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 B(e):
e.wait()
print("hello")
if __name__ == "__main__":
e = threading.Event()
t = threading.Thread(target=B,args=(e,))
t.start()
t.join()