线程
线程是程序最小的执行单元;一个进程可以有多个线程,但是只有一个主线程
Python的标准库提供了两个模块:thread和threading,thread是低级模块,threading是高级模块,对thread进行了封装。绝大多数情况下,我们只需要使用threading这个高级模块。
Thread
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")
基于类实现多线程
import threading
class haha(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__":
ts = []
for i in range(5):
t = haha()
t.start()
ts.append(t)
for i in ts:
t.join()
print('Over')
运行结果
线程锁
多个线程之间 内存是共享的,所以线程比进程轻量。多个线程是可以同时访问内存中的数据的,如果多个线程同时修改一个对象,那这份数据可能会被破坏,Python的threading类中提供了Lock方法,它会返回一个锁对象,一般通过lock.acquire()来获取锁,通过lock.release()来释放锁,对于那种只允许一个线程操作 的数据,一般把对其的操作放在lock.acquire()和lock.release()中间。
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()
print("game over")
信号限制线程数
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()
锁定匹配数量
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()
俩个例子
# 随机生成100个验证码存入本地
import threading
import random
class Myhtread(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.randint(1000,10000)
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 = Myhtread(lock)
t.start()
ts.append(t)
for t in ts:
t.join()
print("Over")
# 获取猫眼榜单top—100的电影名字和评分存入本地
import requests
import re
import threading
class maoyan_top100(threading.Thread):
def __init__(self,start_,end_,lock):
threading.Thread.__init__(self)
self.headers = {
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/76.0.3809.100 Safari/537.36'
}
self.base_url = "https://maoyan.com/board/4?offset=%d"
self.start_ = start_
self.end_ = end_
self.lock = lock
def run(self):
for offset in range(self.start_,self.end_,10):
url = self.base_url % offset
response = requests.get(self.base_url, headers=self.headers)
html = response.text
info_list = self.get_Information(html)
with self.lock:
self.write(info_list)
print("offser {} is ok!".format(offset))
def get_Information(self,html):
information_list = []
for line in html.split('\n'):
if 'class="image-link"' in line:
move_name = line.split('title="')[1].split('"')[0]
print(move_name)
if 'class="integer"' in line:
res = re.search(
'<p class="score"><i class="integer">(\d\.)</i><i class="fraction">(\d)</i></p>',
line)
integer = res.group(1)
fraction = res.group(2)
score = integer + fraction
information_list.append(score)
return information_list
def write(self,info_list):
str_ = str(info_list) + '\n'
with open('move.txt',mode='a',encoding='utf8') as file:
file.write(str_)
if __name__ == "__main__":
threads = []
lock = threading.Lock()
for i in range(2):
t = maoyan_top100(start_=i * 50, end_=(i + 1) * 50,lock=lock)
t.start()
threads.append(t)
for t in threads:
t.join()
print("Over")
线程通信(event)
import threading
import time
def A(e):
e.wait()
print("Hello")
def B(self):
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()
t2.join()
例子
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 World!')
if __name__=="__main__":
e = threading.Event()
t = threading.Thread(target=A,args=(e,))
t.start()
t.join()
运行结果