• 查看线程的id名字正在运行的线程数量[getName()--ident--enumerate--activeCount]--线程池--协程(gevent)--优先级队列(LifoQueue)


    一、如何查看线程的id和名字

    方法介绍:
        threading.current_thread().getName()  #查看线程的名字
        threading.current_thread().ident  #查看线程的id
        threading.enumerate(): 返回一个包含正在运行的线程的list。正在运行指线程启动后、结束前,不包括启动前和终止后的线程。
        threading.activeCount(): 返回正在运行的线程数量,与len(threading.enumerate())有相同的结果。
    import threading
    import time
    from threading import Thread,current_thread
    def f1(n):
        pass
        # time.sleep(1)
        # print("子线程名字",current_thread().getName())
        # print("%s号线程的任务"%n)
    if __name__ == '__main__':
        t1 = Thread(target=f1,args=(1,))
        t1.start()
        print("主线程名字",current_thread().getName())  #查看线程的名字
        print("主线程id",current_thread().ident())  #查看线程的id
        print(current_thread())  #打印结果为线程的名字
        print(threading.enumerate())  #返回包含正在运行的线程的list
        print(threading.activeCount())  #返回正在运行的线程的数量

    二、线程池

    线程池的作用:
        服务开启的进程数或者线程数都会随着并发的额客户端数目的增多而增多,这会对服务器主机带来巨大的压力,甚至于不堪重负而瘫痪,所以我们必须对服务开启的进程数或线程数加以控制.
    线程池个数默认是 cpu个数*5,开启线程池和进程池,就一个模块的名字不一样,其他方法都一样,之前学的pool方法开启进程池是一种补充.
    concurrent.futures  #需要导入的模块 (模块提供了高度封装的异步调用接口)
    ThreadPoolExecutor #线程池(提供异步调用)

    ProcessPoolExecutor #进程池(提供异步调用)
    基本方法:
    submit() #向线程池异步提交任务,相当于Pool模块的apply_asinc,提交完后,线程里面的内容就开始运行,可以看到线程里面的执行(eg.print(...))
       p = ThreadPoolExecutor(4) #默认的线程个数是cpu个数*5
       a = p.map(f1,可迭代的对象) #异步执行,map 取代for 循环submit的操作.可以用变量(a)接收返回值,(a)是个可迭代对象

       shutdown()#锁定线程池,等待线程池中所有以提交任务全部执行完毕. 相当于进程池的pool.close()+pool.join()
       add_done_callback(fn) #回调函数
       res.result() #获取返回值,如果还没有出来返回值,会等待,阻塞程序
    注意:

      submit和map必须在shutdown之前
    #创建线程池
    from
    concurrent.futures import ThreadPoolExecutor def f1(n):
    print(n)
    return n*n if __name__ == '__main__': tp = ThreadPoolExecutor(4) # a = tp.map(f1,range(10)) #异步提交任务,参数同样是任务名称,可迭代对象 res_list = [] for i in range(10): res = tp.submit(f1,i) #submit是给线程池异步提交任务,提交完后,线程开始运行,可以看到线程里面的执行(eg.print(...)) res_list.append(res) #将返回值添加到一个列表 tp.shutdown() #主线程等待所有提交给线程池的任务,全部执行完毕(相当于close+join) for r in res_list: #迭代着取线程执行完毕的返回值 print(r.result()) print("主线程结束")
    如何一次性获取线程池的返回值:
    1. res = tp.submit(f1,i)  #submit是给线程池异步提交任务,线程内容开始执行   (eg.print(...)),返回值需要接收才能得到
    2. res_list.append(res) #把线程执行的返回值放进一个列表
    3. tp.shutdown() #主线程等待所有提交给线程池的任务,全部执行完毕(相当于close+join)
    4. print("开始接收返回值了")
    5. for r in res_list:
          print(r.result()) #result()是获取返回值,相当于Pool的get()
    6. print("主线程结束")    
    #创建进程池
    from
    concurrent.futures import ProcessPoolExecutor def f1(n): return n*n if __name__ == '__main__': tp = ProcessPoolExecutor(4) # tp.map(f1,range(10)) #异步提交任务,参数同样是任务名称,可迭代对象 res_list = [] for i in range(10): res = tp.submit(f1,i) #submit是给线程池异步提交任务,此方法提交后,进程里的内容就开始 res_list.append(res) tp.shutdown() #主线程等待所有提交给线程池的任务,全部执行完毕(相当于close+join) for r in res_list: print(r.result()) #ProcessPoolExecutor的result相当于Pool的get()方法取返回值 print("主进程结束")

     线程池的回调函数

    from concurrent.futures import ThreadPoolExecutor,ProcessPoolExecutor
    def f1(n,s):
        return n+s
    def f2(n):
        print("回调函数>>",n.result()) #此处加result是取里面值,否则出来的是一个结果集地址
    if __name__ == '__main__':
        tp = ThreadPoolExecutor(4)
        res = tp.submit(f1,11,12).add_done_callback(f2)

     三、协程 gevent(一个线程可以开500w条协程)

    什么是协程:
        单线程下的并发称为协程微线程纤程.协程是一种用户态的轻量级线程,即协程是由用户程序自己控制调度
    注意:
        1.python 的线程属于内核级别的,即由操作系统的控制调用(如单线程遇到IO或者执行时间过长
    就会被迫交出cpu执行权限,切换其他线程执行)
        2.单线程内开启协程,一旦遇到IO,就会从应用程序级别(而非操作系统)控制切换,一次来提升效率)(非IO操作的切换与效率无关)
    缺点:
        1.协程的本质是单线程下,无法利用多核,可以是一个程序开启多个进程,每个进程内开启多个线程,每个线程内开启协程
        2.协程指的是单个线程,因而一旦协程出现阻塞,将会阻塞整个线程
    什么是gevent:
        gevent是一个第三方库,可以实现并发同步或异步编程,一个协程遇到IO操作自动切换到其他协程.
    参数介绍:
    g1 = gevent.spawn(func2,1)#创建一个协程对象g1,参数1是函数名,后面的参数都是传递给该函数的形参.
    gevent.joinall([g1,g2])  #相当于g1.join()和g2.join()
    g1.value #拿到func1的返回值
    如何确定是一个协程,验证它在一个线程里面,而没有开启其他线程:
    print(threading.current_thread().getName())  #放在线程里面,返回的值是DummyThread-n,即假线程,是一个协程
    具体操作:
    遇到IO会自动切换任务
    import gevent
    from gevent import monkey;monkey.patch_all() #可以理解为给gevent打补丁,让它能够知道time.sleep(2)跟gevent.sleep(2)一样,该补丁必须放在打补丁的前面,如time,socket模块之前.def eat(name):
        print("%seat 1"%name)
        time.sleep(2)
        print("%s eat 2"%name)
    def play(name):
        print("%s play 1"%name)
        time.sleep(1)
        print("%s play 2"%name)
    g1 = gevent.spawn(eat,"egon")
    g2 = gevent.spawn(play,name="egon")
    gevent.joinall([g1,g2]) #gevent.joinall([g1,g2]) = g1.join()和g2.join()
    print("")
    打印结果:
    egoneat 1
    egon play 1
    egon play 2
    egon eat 2

    四、greenlet模块

    如果我们在单个线程你有20个任务,想要实现在多个任务之间切换,使用yield生成器的方式过于麻烦(需要初始化一次生成器,然后再调用send...非常麻烦),而使用greenlet模块可以非常简单的实现这20个任务直接的切换.
    
    但是在没有IO的情况下或者没有重复开辟的内存空间的操作,反而会降低程序的执行速度.
    
    greenlet只是提供了一种比generator更加便捷的切换方式.当切到一个任务执行时遇到IO,就原地阻塞,仍然没有解决遇到IO自动切换来提升效率的问题

    五、先进后出和优先级队列

    先进后出队列:
      queue.LifoQueue() #先进后出队列   注意:先进去的,最后出来
    优先级队列:
      queue,priorityQueue() #存储数据时可设置优先级的队列
      注意:put 的数据是一个元组,元组的第一个参数是优先级数字,数字越小,优先级越高,越先被get到取出来,第二个参数是put进去的的值1
       如果优先级相同,将会比较值,值不能是字典数据类型.
    #先进后出实例
    import queue
    q=queue.LifoQueue() #队列,类似于栈,栈我们提过吗,是不是先进后出的顺序啊
    q.put('first')
    q.put('second')
    # q.put_nowait()
    
    print(q.get())
    print(q.get())
    # q.get_nowait()
    '''
    结果(后进先出):
    third
    second
    first
    '''
     
    #优先级队列演示
    import queue q = queue.PriorityQueue(5) #注意队列的长度,因为后面put多了,会阻塞 q.put((9,"小黑")) q.put((6,"大黑")) q.put((7,"不黑")) #如果优先级数字相同,会比较第二个参数的元素的ascii表中的位置,如果数据类型不同会报错.
    q.put((7,"很黑")) print(q.get()) print(q.get()) print(q.get())
  • 相关阅读:
    HTML<lable for="">标签的for属性。
    Microsoft_Office_Word_遇到问题需要关闭。我们对此引起的不便表示抱歉,问题解决方案
    AnyChart的资料,以后看
    JQquery 鼠标悬浮提示
    如何在SQL Server查询语句(Select)中检索存储过程(Store Procedure)的结果集?
    JQuery UI selectable
    SqlServer 动态添加服务器
    基于CyberGarage库的dlna开发(android)
    自定义实现圆形播放进度条(android,飞一般的感觉)
    Lance老师UI系列教程第一课>QQ设置界面的实现(android)
  • 原文地址:https://www.cnblogs.com/lgw1171435560/p/10266263.html
Copyright © 2020-2023  润新知