• python 线程 进程


    1、进程与线程优、缺点的比较
    总言:使用进程和线程的目的,提高执行效率

    进程:

      优点:能利用机器的多核性能,同时进行多个操作。

      缺点:需要耗费资源,重新开辟内存空间,耗内存。

    线程:

      优点:共享内存(资源),做IO操作时,可以创造并发操作。

      缺点:抢占资源。

    总结:进程并不是越多越好,最好CPU个数 = 进程个数。

       线程也并不是越多越好,应根据业务需求来确定个数,因为请求上下文切换非常耗时。

    2、适用情况
    IO密集型(不用CPU) :适合多线程

    计算密集型(要用CPU):适合多进程

    3、线程
      (1)线程的创建(threading模块)
    import threading #导入该模块
    import time

    def f0():
    pass

    def f1(a1,a2):
    time.sleep(1)
    print(a1,a2)
    f0()

    #创建子线程,任务为f1(),参数为args的元祖
    t = threading.Thread(target=f1,args=(123,456,))
    #默认setDaemon为false,主线程要等待子线程执行完毕后再结束
    #设置为True后,就不等待
    t.setDaemon(True)
    t.start() #告诉线程我们准备好了

    (2)主线程是否等待子线程

      t.setDaemon(True/False)

      用于设置主线程执行完毕后,是否等待子线程,默认为false,要等待。

      (3)主线程是否等待某个子线程执行完毕

      t.join()  一直等待

      t.join(2)最多等待该子线程2s

    (4)线程锁RLock

      避免因并发操作而造成脏数据,线程锁能锁住全部子线程,同一时刻允许一个线程执行操作。

    #未使用线程锁时
    import threading
    import time

    gl_num = 0

    def show(arg):
    global gl_num
    time.sleep(0.5)
    gl_num +=1
    print(gl_num)

    #开了10个线程,同时都对全局变量gl_num进行操作
    for i in range(10):
    t = threading.Thread(target=show, args=(i,))
    t.start()

    print('main thread stop')

    #使用了线程锁时
    import threading
    import time

    gl_num = 0

    lock = threading.RLock() #创建锁

    def Func():
    lock.acquire() #锁定
    global gl_num
    gl_num += 1
    time.sleep(0.25)
    print(gl_num)
    lock.release() #释放锁

    for i in range(10):
    t = threading.Thread(target=Func)
    t.start()
    print('main thread stop')

    (5)事件(Event)

    python线程的事件用于主线程控制其他线程的执行,事件主要提供了三个方法 set、wait、clear。

    事件处理的机制:全局定义了一个“Flag”,如果“Flag”值为 False,那么当程序执行 event.wait 方法时就会阻塞,如果“Flag”值为True,那么event.wait 方法时便不再阻塞。

      event.wait()  等待绿灯开启,再继续执行

      event.clear()设为红灯

      event.set()   设为绿灯

    import threading

    def do(event):
    print('start')
    event.wait() #阻塞住,等待绿灯。event_obj.set()语句执行后,又回来继续执行下一句
    print('execute')

    event_obj = threading.Event()
    for i in range(3):
    t = threading.Thread(target=do, args=(event_obj,))
    t.start()

    event_obj.clear() #设为红灯
    inp = input('input:')
    if inp == 'true':
    event_obj.set() #设为绿灯

     (6)生产者消费者模型、队列(先进先出)(queue模块)

    4、进程
    (1)创建进程(multiprocessing模块)

    import multiprocessing
    import time

    def f1(a1):
    time.sleep(3)
    print(a1)

    if __name__ == '__main__': #Windows上,进程语句必须放在main里面
    #创建进程,任务为执行f1(),参数为11,由元祖封装
    t = multiprocessing.Process(target=f1,args=(11,))
    # 当daemon设为true时,主进程结束后就不再等待子进程了,默认为false要等待
    t.daemon = True #所以结果没有打印出 11
    t.start()

    t = multiprocessing.Process(target=f1,args=(22,))
    t.start()
    print('end')


    (2)主进程是否等待子进程

      t.setDaemon(True/False)

      用于设置主进程执行完毕后,是否等待子进程,默认为false,要等待。

     (3)主进程是否等待某个子进程执行完毕

      t.join() 一直等待

      t.join(2)最多等待该子进程2s

      (4)线程与进程,数据之间是否共享对比
      默认每个进程之间的数据是不共享的,各做各的。

      而每个线程之间的数据是共享的。 
    #进程操作时,数据是不共享的
    from multiprocessing import Process

    li = []
    def foo(i):
    li.append(i)
    print('say hi',li)

    if __name__ == '__main__':
    for i in range(10):
    p = Process(target=foo,args=(i,))
    p.start()

    线程处理时,数据是共享的,将process改为thread,结果为:

    (5)特殊的数据容器
      如果想要多个进程同时操作一份数据,则需要特殊的容器。

      方法一:Array数组(不推荐)

        a.创建时需要规定大小,切不能改变。

        b.内部数据必须统一为相同类型,字符串、数字等。

      方法二:manager.dict()共享数据(推荐)

        创建: m = Manager()

           dict = m.dict()
    from multiprocessing import Process,Manager

    def Foo(i,dic):
    dic[i] = 100+i
    print(len(dic))

    # for k,v in dic.items():
    # print(k,v)
    if __name__ == '__main__':
    manager = Manager()
    dic = manager.dict()
    # dic = {} #dic为普通字典时,返回值为 1 1

    for i in range(2):
    p = Process(target=Foo,args=(i,dic))
    p.start()
    p.join()

    (6)进程池(python中已创建好) pool

    from multiprocessing import Pool
    import time

    def f1(a1):
    time.sleep(1)
    print(a1)
    return 1000

    def f2(arg):
    print(arg)

    if __name__ == '__main__':

    pool = Pool(5)
    # pool.apply(f1,(2,))
    for i in range(10):
    pool.apply_async(func=f1, args=(i,), callback=f2)#特别注意args跟的参数为元祖类型
    #callback=f2表示回调函数,将f1 return的值作为参数传给f2
    pool.close()
    pool.join()#等待子进程执行完

    pool.apply()和pool.apply_async()对比:
    pool.apply() :每一个任务都是排队执行的,内部有join()方法,会等待子进程
    pool.apply_async():每一个任务都是并发执行,且可以设置回调函数,内部无join()方法,
    进程deamon = true,不等待子进程,要想等待子进程,需先pool.close(),再pool.join()

    5、协程(高性能代名词)

    线程和进程的操作时程序出发系统接口,最后的执行者是系统,协程的操作则是程序员。

    存在意义:只使用一个线程,在一个线程中规定某个代码块执行顺序。
    适用于: IO密集型操作

    方法一:greenlet模块
        需手动切换任务(不推荐)

    方法二:gevent模块(本质也是基于greenlet)
        自动切换任务,谁先回来就先处理谁(推荐)
    import gevent

    def foo():
    print('1')
    gevent.sleep(0) #切换标志
    print('2')


    def bar():
    print('3')
    gevent.sleep(0) #切换标志
    print('4')


    gevent.joinall([
    gevent.spawn(foo),
    gevent.spawn(bar),
    ])

  • 相关阅读:
    input输入框只能输入数字和 小数点后两位
    HAVING 子句
    GROUP BY 语句
    SUM()函数
    COUNT()函数
    MySQL AVG() 函数
    adb(16)-查看实时资源占用情况top
    adb(15)-刷机相关命令
    adb(14)-设备重启/检测root
    adb(13)-设置系统日期和时间
  • 原文地址:https://www.cnblogs.com/mmbbflyer/p/7754946.html
Copyright © 2020-2023  润新知