zoukankan      html  css  js  c++  java
  • 多进程多线程与进程池线程池及协程

    1,进程和线程的区别

    打开一个程序相当于一个进程,而程序中的读取数据,传输数据等不同的功能相当于不同的线程。线程没有利用到多核的优势,一个进程内的所有线程的内存是共享的,但是开启线程不会消耗太大的资源;进程中的内存都是独立的,每次开启一个进程都需要申请新的内存空间。

    2,开启进程(线程)的两种方法

    进程:

    #使用方法来来使用多进程
    import time
    import random
    from multiprocessing import Process
    def piao(name):
        print('%s piaoing' %name)
        time.sleep(random.randrange(1,5))
        print('%s piao end' %name)
    if __name__ == '__main__':
        #实例化得到四个对象
        p1=Process(target=piao,args=('egon',)) #必须加,号
        p2=Process(target=piao,args=('alex',))
        p3=Process(target=piao,args=('wupeqi',))
        p4=Process(target=piao,args=('yuanhao',))
        #调用对象下的方法,开启四个进程
        p1.start()
        p2.start()
        p3.start()
        p4.start()
        print('')
    
    #使用类来使用多进程
    import time
    import random
    from multiprocessing import Process
    class Piao(Process):
    def __init__(self,name):
    super().__init__()
    self.name=name
    def run(self):
    print('%s piaoing' %self.name)
    time.sleep(random.randrange(1,5))
    print('%s piao end' %self.name)
    if __name__ == '__main__':
    #实例化得到四个对象
    p1=Piao('egon')
    p2=Piao('alex')
    p3=Piao('wupeiqi')
    p4=Piao('yuanhao')
    #调用对象下的方法,开启四个进程
    p1.start() #start会自动调用run
    p2.start()
    p3.start()
    p4.start()
    print('主')

     线程

    因为GIL的存在,所以在Cpython解释器中,同一个进程下开启的多线程,同一时刻只能有一个线程执行,无法利用多核优势
    #线程中使用方法来使用多线程
    from threading import Thread
    import time
    def sayhi(name):
    time.sleep(2)
    print('%s say hello' %name)
    if __name__ == '__main__':
    t=Thread(target=sayhi,args=('egon',))
    t.start()
    print('主线程')
    #线程中使用类来使用多线程
    from threading import Thread
    import time
    class Sayhi(Thread):
        def __init__(self,name):
            super().__init__()
            self.name=name
        def run(self):
            time.sleep(2)
            print('%s say hello' % self.name)
    if __name__ == '__main__':
        t = Sayhi('egon')
        t.start()
        print('主线程')

    3,进程池和线程池

    #进程池使用pool.apply加入进程池是并行的,没有并行的效果
    from multiprocessing import Process, Pool
    # 从multiprocessing导入pool
    
    import time, os
    
    
    def Foo(i):
        time.sleep(2)
        print("in process", os.getpid())  # 打印进程id
        return i + 100
    
    
    def Bar(arg):
        print('-->exec done:', arg)
    
    
    if __name__ == '__main__':  ##这行代码用途是如果主动执行该代码的.py文件,则该代码下面的代码可以被执行;如果该.py模块被导入到其他模块中,从其他模块执行该.py模块,则该行下面的代码不会被执行。  有些时候可以用这种方式用于测试,在该行代码下面写一些测试代码。。
        pool = Pool(5)  # 同时只能放入5个进程
    
        for i in range(10):  # 创建10个进程,但是因为pool的限制,只有放入进程池中的5个进程才会被执行(),其他的被挂起了,如果进程池中其中有两个进程执行完了,就会补进2个进程进去。
            # pool.apply_async(func=Foo, args=(i,), callback=Bar)
            pool.apply(func=Foo, args=(i,))  # pool.apply用来将进程放入pool
    
        print('end')  # 执行完毕
        pool.close()  # 允许pool中的进程关闭(close必须在join前面,可以理解close相当于一个开关吧)
        pool.join()  # 进程池中进程执行完毕后再关闭,如果注释,那么程序直接关闭。
    #pool.apply_async  加入进程池的方式是并行
    from
    multiprocessing import Process, Pool import time, os

    def Foo(i): time.sleep(2) print("in process", os.getpid()) return i + 100 def Bar(arg): print('-->exec done:', arg) if __name__ == '__main__': pool = Pool(5) for i in range(10): pool.apply_async(func=Foo, args=(i,)) ## 使用pool.apply_async就可以并行了 print('end') pool.close() pool.join()
    #并行运行并且使用回调函数
    from multiprocessing import Process, Pool
    import time, os
    
    
    def Foo(i):
        time.sleep(2)
        print("in process", os.getpid())
        return i + 100
    
    
    def Bar(arg):
        print('-->exec done:', arg, os.getpid())
    
    
    if __name__ == '__main__':
        pool = Pool(5)
    
        print("主进程:", os.getpid())  # 打印主进程id
        for i in range(10):
            pool.apply_async(func=Foo, args=(i,), callback=Bar)
            ##callback叫做回调,就是当执行完了func=Foo后,才会执行callback=Bar(每个进程执行完了后都会执行回调)。
            ## 回调可以用于当执行完代码后做一些后续操作,比如查看完命令后,通过回调进行备份;或者执行完什么动作后,做个日志等。
            ## 备份、写日志等在子进程中也可以执行,但是为什么要用回调呢! 这是因为如果用子进程,有10个子进程就得连接数据库十次,而使用回调的话是用主进程连接数据库,所以只连接一次就可以了,这样写能大大提高运行效率。
            ##通过主进程建立数据库的连接的话,因为在同一个进程中只能在数据库建立一次连接,所以即使是多次被子进程回调,也不会重复建立连接的,因为数据库会限制同一个进程最大连接数,这都是有数据库设置的。
    
        print('end')
        pool.close()
        pool.join()

     4、协程

    线程和协程的区别:线程的切换时操作系统执行的,分两种情况1是该任务发生了阻塞,任务运行时间到了或者一个优先级更高的任务代替了它。

    而协程是用户程序自己控制调度的。

    from datetime import datetime
    import asyncio
    
    async def add(n):
        print(datetime.now().strftime('%H:%M:%S.%f'))
        count = 0
        for i in range(n):
            count += i
        print(datetime.now().strftime('%H:%M:%S.%f'))
        return count
    
    async def fun(n):
        res = await add(n)
        print(f'res = {res}')
    
    loop = asyncio.get_event_loop()
    tasks = [fun(20000000), fun(30000000)]
    loop.run_until_complete(asyncio.wait(tasks))
    loop.close()
    使用asyncio开启协程
    import time
    
    import queue
    
    
    def consumer(name):
        print("--->starting eating baozi...")
        while True:
            new_baozi = yield
            print("[%s] is eating baozi %s" % (name, new_baozi))
            # time.sleep(5)
    
    
    def producer():
        r = con.__next__()
        r = con2.__next__()
        n = 0
        while n < 5:
            n += 1
            con.send(n)
            con2.send(n)
            print("33[32;1m[producer]33[0m is making baozi %s" % n)
    
    
    if __name__ == '__main__':
        con = consumer("c1")
        con2 = consumer("c2")
        p = producer()
    使用yield开启携程
        import gevent
        def eat(name):
            print('%s eat 1' %name)
            gevent.sleep(2)
            print('%s eat 2' %name)
        def play(name):
            print('%s play 1' %name)
            gevent.sleep(1)
            print('%s play 2' %name)
        g1=gevent.spawn(eat,'egon')
        g2=gevent.spawn(play,name='egon')
        g1.join()
        g2.join()
        #或者gevent.joinall([g1,g2])
        print('')
    使用gevent实现协程
    人生苦短,我用cnblog
  • 相关阅读:
    视图创建
    根据表格作业题
    表格 作业题练习
    创建表格 练习题
    聚合函数、数学函数、日期时间函数
    接口自动化框架
    python+request+Excel 几十份接口测试用例一起自动化测试的接口测试框架
    python3 函数
    pip源头
    爬虫
  • 原文地址:https://www.cnblogs.com/wuzhibinsuib/p/12654625.html
Copyright © 2011-2022 走看看