线程和进程区分
进程是资源分配的单位,线程是资源调度的单位 当一个程序运行起来,操作系统会分配一系列资源给这个程序去使用,这些资源称为进程 在程序执行必须由线程来完成
在一个进程中,一定会有至少一个线程在运行
- 主进程结束,其他子进程依旧运行
- 主线程结束,其他子线程也一起结束
实现多任务的方式
- 多线程 在一个进程中创建多个线程来执行任务,缺点:多线程之间可以共享数据,但容易造成资源竞争问题(线程安全问题)
- 多进程 创建多个进程来完成任务,缺点:进程占用的资源过多,各个进程的资源时相对独立
创建进程的方式
def task():
"""任务函数"""
def main():
p = multiprocessing.Process(target=task,args=(10,),kwargs={})
p.start() # 创建子进程,并启动起来
p.join() # 阻塞当前进程,等待p的进程结束后再向下执行
if __name__ == "__main__":
main()
def task():
"""任务函数"""
def main():
po = Pool(3) # 定义一个进程池,最大进程数3
for i in range(0, 1000):
po.apply_async(func=task, args=(10,))
po.close() # 关闭进程池,不在接受新的任务
# 必须加上,否则主进程结束,进程池的进程也会结束
po.join() # 让主进程阻塞,等待进程池中所有任务结束
if __name__ == "__main__":
main()
进程池的优点
- 降低资源消耗。通过重复利用已创建的进程降低进程创建和销毁造成的消耗。
- 提高响应速度。当任务到达时,任务可以不需要等到进程创建就能立即执行。
- 提高进程的可管理性。进程是稀缺资源,如果无限制的创建,不仅会消耗系统资源,还会降低系统的稳定性,使用进程池可以进行统一的分配,调优和监控
Queue使用方法:
- Queue.qsize():返回当前队列包含的消息数量;
- Queue.empty():如果队列为空,返回True,反之False ;
- Queue.full():如果队列满了,返回True,反之False;
- Queue.get():获取队列中的一条消息,然后将其从列队中移除,可传参超时时长。
- Queue.get_nowait():相当Queue.get(False),取不到值时触发异常:Empty;
- Queue.put():将一个值添加进数列,可传参超时时长。
- Queue.put_nowait():相当于Queue.put(item,False),当队列满了时报错:Full。