线程与进程

进程

  • 进程就是程序执行的载体;
  • 打开的每个软件、游戏,执行的每一个python脚本都是一个进程;

多进程

  • 可以同时启动多个进程,这些进程都是在执行程序,但是他们互不干扰,各自执行自己的业务逻辑
  • 并行处理:多个cpu内核同时执行,多进程在不同的内核(跑道)中执行(同一时间处理多个事情)
  • 进程负责吸收足够程序跑起来的资源(cup,内存),并交给线程,线程则是真正执行业务逻辑的角色;
  • 进程提供线程执行程序的前置要求,线程在重组的资源配备下,去执行程序

线程

  • 先有进程再有线程
  • 主线程、子线程

多线程

  • 并发:单个cpu内核中多个线程同时工作。把一个核心中多个时间片上同时处理线程的行为称为并发。

多进程的问题

  • 通过进程模块执行的函数无法获取返回值
  • 多个进程同时修改文件可能会出现错误
  • 进程数量太多可能会造成资源不足,甚至死机等情况

进程池

  • 包含一定数量进程的池子该进程池中的进程伴随进程池一起被创建。
  • 可以被重复使用。
  • 进程池关闭时,池中的进程也会被关闭
  • 当有任务执行时,会首先判断池子中有没有空闲的进程,如果有空闲的进程,则该任务交给空闲的进程,如果没有则需要等待,直到有执行完成的空闲的进程

进程池的创建–multiprocessing

  • 创建进程池:pool = multiprocessing.Pool(Processcount)
  • 任务加入进程池(异步):pool.apply_async(func, args)
  • 关闭进程池:.close
  • 等待进程池任务结束:.join

进程锁

  • 看到进程就会给进程上一把锁,进门上锁,开门解锁
from multiprocessing import Manager
manage = Manager()
lock = manager.Lock()
  • 上锁:acquire
  • 开锁(解锁):release

进程的通信

  • 什么是进程的通信:当两个进程建立通话之后,两个进程之间就会建立一条隐形的队列。A进程要发信息到B进程就需要队列的帮助,队列支持发送消息和接收消息。

队列的创建:

  • send:q.put(message) 信息放入队列
  • receive:q.get() 获取队列信息
if __name__ == '__main__':
    # 创建一个队列
    q = multiprocessing.Queue()
    # 实例化work类
    work = Work(q)
    # 定义一个传入的进程
    # send = multiprocessing.Process(target=work.send, args=(1,2,3))
    send = multiprocessing.Process(target=work.send, args=[{'name':'小慕'}])
    # 定义一个接收的进程
    recv = multiprocessing.Process(target=work.receive)
    send_all_p = multiprocessing.Process(target=work.send_all)

    send_all_p.start()
    send.start()
    recv.start()

    send_all_p.join()  # 阻塞最长使用率的进程
    recv.terminate()

线程的创建

  • threading:Thread(target, args) 创建线程(target是要执行的函数,args是执行这个函数需要传入的参数)
    线程对象的方法
  • 启动线程——start()
  • 阻塞直到线程执行结束——join(timeout=None)
  • 获取线程的名字——getName()
  • 设置线程的名字——setName(name)
  • 判断线程是否存活——is_alive()
  • 守护线程——setDaemon(True)
    定义一个列表A,再定义一个列表B,将A中的内容随机写到B中并删除随机的数据。
def work():
    if len(lists) == 0:
        return []
    data = random.choice(lists)  # 随机获取列表中的成员
    lists.remove(data)
    new_data = '%s_new' % data
    lists_new.append(new_data)
    time.sleep(1)

线程的问题

  • 通过线程执行的函数无法获得返回值
  • 多个线程同时修改文件可能造成数据错乱
  • 线程池的创建——concurrent
    futures.ThreasPoolExecutor
    tpool = ThreadPoolExecutor(max_workers) #线程池对象
  • 往线程池中加入任务:submit(target, args)
  • 线程池中的某个线程是否完成了任务:done()
  • 获取当前线程执行任务的结果:result()

GIL全局锁

  1. GIL的作用
  • 使得python的多线程无法在多个cpu上执行任务,只能在单一cpu上执行任务,限制了多线程的任务,使得不那么多线程了;
  • 保障线程之间的安全;pypy解释器不含有GIL锁;
  • 使用多进程+多线程的方式弥补这一问题,通过使用多个进程在每个cpu跑道上执行任务,并且每个跑道上再执行多个线程,让他们去到各自的时间片上去运行。
  1. 总结多线程与多进程:在主进程或者主线程中创建多个子进程或者子线程,子进程或者子线程的运行不会影响主进程和主线程的代码执行,从而使得代码可以在多个线程或多个进程下提高代码质量。

异步

  1. 异步的目的是为了不阻塞。

异步属于轻量级的线程 协程,是进程下的一部分
多进程与多线程无法获取函数的返回值, 但是异步可以获取函数的返回值
主进程需要异步才可以使用异步
更适合文件读写使用
3. async和await关键字
async定义异步 async def test():
return ‘a’
await执行异步 async def handle():
result = await test()
asyncio调用saync函数
4. gevent
pip install gevent
Microsoft Visual C++
pip install wheel
spawn 创建协程对象 返回值是一个协程对象
joinall 批量处理协程对象

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值