线程和进程的使用
-
线程的继承用法(
class Spider(Thread)
)from threading import Thread # 继承线程的类 class DownloadThread(Thread): def __init__(self, url): super().__init__() self.url = url # 更改线程运行要执行的任务 def run(self) -> None: # 确定需要在子线程中完成的任务 print(f'{self.url}开始下载:{datetime.now()}') time.sleep(1) print(f'{self.url}下载结束:{datetime.now()}') t1 = DownloadThread('肖生克的救赎') t2 = DownloadThread('阿甘正传') t3 = DownloadThread('霸王别姬') t1.start() t2.start() t3.start()
-
多进程的队列(
from multiprocessing import Queue
)# 多进程的队列 from multiprocessing import Queue # 使用多进程队列中需要注意:1.将队列定义全局变量 2.队列对象必须通过在子进程中调用的函数的参数传递到进程中去 def download(name, queue: Queue): print(f'{name}开始下载!') time.sleep(1) print(f'{name}下载完成!') # return name+'数据' # queue.put(name+'数据') # 往进程中添加数据 queue.put([f'{name}10', f'{name}20']) if __name__ == '__main__': q = Queue() p1 = Process(target=download, args=('肖生克的救赎', q)) p2 = Process(target=download, args=('阿甘正传', q)) p1.start() p2.start() # p1.join() # p2.join() # 获取两个进程产生的数据 print(q.get()) # 获取队列中的数据;如果获取的时候队列中没有数据会阻塞线程一直等,等到有数据或者超时为止 print(q.get()) # print(q.get()) # print(q.get(timeout=2)) print('=============================')
-
进程池(
from multiprocessing import Pool
)from multiprocessing import Pool def download(name): print(f'{name}开始下载') time.sleep(1) print(f'{name}下载结束') if __name__ == '__main__': # 1.创建进程池对象 pool = Pool(maxtasksperchild=3) # 2.添加任务 # 1)添加单个任务 # apply - 添加同步执行 # apply_async - 添加异步执行 pool.apply_async(download, args=('肖生克的救赎',)) pool.apply_async(download, args=('触不可及',)) # 2)同时添加多个任务 # pool.map(download, ['V字仇杀队', '恐怖游轮', '林中小屋']) # 3.关闭 pool.close() # 停止添加任务 # pool.apply(download, args=('摔跤吧,爸爸',)) # 4. 等待 pool.join() print('===========全部完成===========')
-
多线程的数据安全(
Rlock
)from threading import Thread, RLock # 加锁的原则:一个数据对应一个固定的锁对象 # 加锁的方法:1.创建锁对象(RLock) 2.加锁 3.释放锁 # 使用锁的注意事项:防止死锁(要保证加锁以后不管线程发生了什么,锁一定要得到释放) # 多个线程或者多个进程争夺同一队列的时候不会出现线程安全问题(队列本身就是线程安全) def sell(n): global num # 方法一: # num_lock.acquire() # try: # t = num # if n == 2: # raise ValueError # time.sleep(1) # num = t - n # finally: # num_lock.release() # finally不管是否执行异常 都会解锁 # 方法二 # with 自动解锁 with num_lock: t = num if n == 2: raise ValueError time.sleep(1) num = t - n t1 = Thread(target=sell, args=(1, )) t2 = Thread(target=sell, args=(2,)) t3 = Thread(target=sell, args=(4,)) t1.start() t2.start() t3.start() t1.join() t2.join() t3.join() print('余票:', num)
-
守护线程(
daemon=True
)# 如果一个程序有多个线程,只有在所有的线程都结束整个程序才会结束 # 线程结束:a.线程中的任务完成(对应的函数结束) b.出现异常 # 守护线程:会随着主线程结束而结束的线程就是守护线程 print('==============') def func1(): print('子线程1开始') time.sleep(5) print('子线程1结束') def func2(): print('子线程2开始') time.sleep(2) print('子线程2结束') # 设置守护线程 t1 = Thread(target=func1, daemon=True) # 给线程 赋值 daemon=True 该线程就是守护进程 t1.start() t2 = Thread(target=func2) t2.setDaemon(True) t2.start() print([1, 2][10]) time.sleep(7) print('主线程结束!')