zoukankan      html  css  js  c++  java
  • Python中的进程

    进程

    from multiprocessing import Process
    import time
    
    def start(name):
        time.sleep(1)
        print('hello', name)
    
    if __name__ == '__main__':
        # 开辟一个进程
        p = Process(target=start, args=('zhangsan',))
        # 再开辟一个进程
        p1 = Process(target=start, args=('lisi',))
        p.start()
        p1.start()
        p.join()
    

    gai

    进程间通讯,每个进程都有自己的内存空间,因此不同进程内存是不共享的,要想实现两个进程间的数据交换,有几种方法

    Queue(队列)

    def start(q):
        q.put('hello')
    
    if __name__ == '__main__':
        q = Queue()
        p = Process(target=start, args=(q,))
        p.start()
        print(q.get())
        p.join()
    

    GAI

    Pipe(管道)

    把管道的两头分别赋给两个进程,实现两个进程的互相通信

    def start(left_conn):
        right_conn.send('你好')  # 发送
        print(right_conn.recv())  # 接收
        right_conn.close()
    
    if __name__ == '__main__':
        left_conn, right_conn = Pipe()  # 生成管道
        p = Process(target=start, args=(right_conn,))
        p.start()
        print(left_conn.recv())  # 接收
        left_conn.send('你也好')   # 发送
        p.join()
    
    

    左管道发送,右管道接收,随后右管道返回消息,左管道接收,关闭管道
    gai

    Manager实现了进程间真正的通信共享

    
    from multiprocessing import Process, Manager
    
    def f(dic, i):
        dic[i] = i
    if __name__ == '__main__':
        manager = Manager()
        dic = manager.dict()  # 通过manager生成一个字典
        p_list = []
        for i in range(10):
            p = Process(target=f, args=(dic, i))
            p.start()
            p_list.append(p)
        # 等待所有进程执行完毕
        for res in p_list:
            res.join()
        print(dic)
    

    gai

    进程池

    进程池内部维护一个进程序列,当使用时,则去进程池获取一个进程,如果进程池序列中没有可以使用的进程,那么程序就会等待,直到进程池中有可用进程为止。

    from multiprocessing import Process, Pool
    import time
    
    def Foo(i):
    
        return i + 100
    
    def Bar(arg):
        print('number:', arg)
    
    if __name__ == '__main__':
        pool = Pool(3)  # 定义一个进程池,里面有3个进程
        for i in range(10):
            # callback是回调函数,就是在执行完Foo方法后会自动执行Bar函数,并且会把Foo函数的返回值作为参数传入Bar参数
            pool.apply_async(func=Foo, args=(i,), callback=Bar)
        # 必须先关闭进程池,在关闭进程池中的进程
        pool.close()
        # 等待进程池中的进程结束后关闭
        pool.join()
    

    程序会一次拿出来三个从池子里,直到没有
    gai

    from greenlet import greenlet
    import time
    def test1():
        print('---aaa---')
        time.sleep(1)
        gr2.switch()
        print('---bbb---')
        time.sleep(1)
        gr2.switch()
    
    def test2():
        print('-----ccc-----')
        time.sleep(1)
        gr1.switch()
        print('-----ddd-----')
    while 1:
        gr1 = greenlet(test1)
        gr2 = greenlet(test2)
        gr1.switch()
    
    

    协程

    微线程,协程能保留上次调用时的状态,每次过程重入时,就相当于进入上一次调用的状态。

    协程有极高的执行效率,因为子程序切换不是线程切换,而是自身控制,因此,没有线程切换的开销。

    不需要多线程的锁机制,因为它本身只有一个线程,只需要判断状态就好,所以效率高

    因为协程是一个线程进行,所以想要利用多核CPU,就是多进程加协程

    符合协程的条件:

    1. 必须在只有一个单线程里并发
    2. 修改共享数据不需要加锁
    3. 用户程序里自己保存多个控制流的上下文
    4. 一个协程遇到IO操作自动切换到其他协程

    python的两个协程模块:

    • greenlet(执行顺序需要手动控制)
    from greenlet import greenlet
    import time
    def test1():
        print('---aaa---')
        time.sleep(1)
        gr2.switch()
        print('---bbb---')
        time.sleep(1)
        gr2.switch()
    
    def test2():
        print('-----ccc-----')
        time.sleep(1)
        gr1.switch()
        print('-----ddd-----')
    while 1:
        gr1 = greenlet(test1)
        gr2 = greenlet(test2)
        print('开始启动')
        gr1.switch()
    

    手动切换协程,当运行到aaa,切换到ccc,再次切换回去,并且会记录上一次执行完aaa的位置,会从bbb开始执行,如此循环下去,就会出现如下图所示的结果
    gai

  • 相关阅读:
    Java——方法的重载
    JS数据类型之String类型
    常用的正则表达式
    关于前端面试遇到的问题值类型和引用类型,1rem等于多少像素
    JS数据类型之Number类型
    常用前端面试题链接
    Wpf 父子容器的关系 ^
    心情 ^
    sharepoint_wf 启动窗口设计,支配给自由域用户 ^
    WPF 单个触发器、多个触发器、多条件触发器 ^
  • 原文地址:https://www.cnblogs.com/lishi-jie/p/10115428.html
Copyright © 2011-2022 走看看