线程进程补充概念
线程和进程的了解部分,这些概念适用于线程和进程。
可以从threading和multiprocessing中导入,一样的使用。
信号量 Semaphore
信号量在不同的阶段可能对应不同的技术点,在并发编程中信号量指的是锁!!!
这种锁支持多个进程或线程批量共享数据,而不是一个一个地单独享用数据。
-
使用模块Semaphore, 可以从threading或multiprocessing导入
from threading import Thread, Semaphore # from multiprocessing import Semaphore sm = Semaphore(5) # 括号内写数字 写几就表示开设几个坑位 sm.acquire() sm.release()
-
信号量和线程池不一样,信号量是产生一堆线程分批使用数据。
-
线程池是固定的线程,依次处理大批量的任务。
示例
from threading import Thread, Semaphore
import time, random
sm = Semaphore(5) # 括号内写数字 写几就表示开设几个坑位
def task(name):
sm.acquire()
print('%s 正在蹲坑'% name)
time.sleep(random.randint(1, 5))
sm.release()
if __name__ == '__main__':
for i in range(20):
t = Thread(target=task, args=('伞兵%s号'%i, ))
t.start()
事件 Event
线程或进程间是可以设置依赖关系,当A结束时才能执行B。
此时可以使用事件,绑定他们之间的依赖关系。
-
使用Event模块
from threading import Thread, Event # from multiprocessing import Event event = Event() # 造了一个红绿灯 event.set() # 告诉等待红灯的人可以走了,A发出通知,告诉B event.wait() # 等待别人给你发信号, B等待A的通知,
示例
from threading import Thread, Event
import time
event = Event() # 造了一个红绿灯
def light():
print('红灯亮着的')
time.sleep(3)
print('绿灯亮了')
# 告诉等待红灯的人可以走了
event.set()
def car(name):
print('%s 车正在灯红灯'%name)
event.wait() # 等待别人给你发信号
print('%s 车加油门飙车走了'%name)
if __name__ == '__main__':
t = Thread(target=light)
t.start()
for i in range(20):
t = Thread(target=car, args=('%s'%i, ))
t.start()
线程 Q
同一个进程下多个线程间数据共享,此时使用队列主要是为了保证数据安全(队列 = 管道 + 锁)。
- Queue,普通队列,先进先出FIFO
- LifoQueue, 后进先出队列, 类似堆栈,却不同(队列两个口,堆栈一个口)
- PriorityQueue,优先队列, 支持设置消息的等级
- 后进先出队列和优先队列都是继承的普通队列
import queue
# 普通队列, 先进先出
q = queue.Queue(3)
q.put(1)
q.get()
q.get_nowait()
q.get(timeout=3)
q.full()
q.empty()
# 后进先出队列,
q = queue.LifoQueue(3) # last in first out
q.put(1)
q.put(2)
q.put(3)
print(q.get()) # 3
# 优先队列
q = queue.PriorityQueue(4)
q.put((10, '111'))
q.put((100, '222'))
q.put((0, '333'))
q.put((-5, '444'))
print(q.get()) # (-5, '444')
# put括号内放一个元祖 第一个放数字表示优先级, 第二个元素是消息
# 需要注意的是 数字越小优先级越高!!!,即优先get出来
定时器 Timer
定时器,指定n秒后执行某操作
from threading import Timer
def hello():
print("hello, world")
t = Timer(1, hello)
t.start() # after 1 seconds, "hello, world" will be printed
验证码定时器
from threading import Timer
import random,time
class Code:
def __init__(self):
self.make_cache()
def make_cache(self,interval=5):
self.cache=self.make_code()
print(self.cache)
self.t=Timer(interval,self.make_cache)
self.t.start()
def make_code(self,n=4):
res=''
for i in range(n):
s1=str(random.randint(0,9))
s2=chr(random.randint(65,90))
res+=random.choice([s1,s2])
return res
def check(self):
while True:
inp=input('>>: ').strip()
if inp.upper() == self.cache:
print('验证成功',end='\n')
self.t.cancel()
break
if __name__ == '__main__':
obj=Code()
obj.check()
条件 Condition
使得线程等待,只有满足某条件时,才释放n个线程
import threading
def run(n):
con.acquire()
con.wait()
print("run the thread: %s" %n)
con.release()
if __name__ == '__main__':
con = threading.Condition()
for i in range(10):
t = threading.Thread(target=run, args=(i,))
t.start()
while True:
inp = input('>>>')
if inp == 'q':
break
con.acquire()
con.notify(int(inp))
con.release()
def condition_func():
ret = False
inp = input('>>>')
if inp == '1':
ret = True
return ret
def run(n):
con.acquire()
con.wait_for(condition_func)
print("run the thread: %s" %n)
con.release()
if __name__ == '__main__':
con = threading.Condition()
for i in range(10):
t = threading.Thread(target=run, args=(i,))
t.start()