python 线程(其他方法,队列,线程池,协程 greenlet模块 gevent模块)

1.线程的其他方法

from threading import Thread,current_thread
import time
import threading
def f1(n):
    time.sleep(1)
    print('子线程名称',current_thread().getName())#获取线程名
if __name__=='__main__':
    t1=Thread(target=f1,args=(1,))
    t1.start()
    print('主线程名称',current_thread().getName())
    print('主进程id',current_thread().ident)
    print(current_thread())#当前线程的对象
    print(threading.enumerate())#当前正在运行的线程的一个列表
    print(threading.active_count())#当前正在运行的线程的数量
#########结果########
主线程名称 MainThread
主进程id 7512
<_MainThread(MainThread, started 7512)>
[<_MainThread(MainThread, started 7512)>, <Thread(Thread-1, started 5680)>]
2
子线程名称 Thread-1

2.线程队列

import queue
###先进先出
q=queue.Queue(3)
q.put(1)
q.put(2)
print('当前队列内容长度',q.qsize())
q.put(3)
print('查看队列是否满了',q.full())

print(q.get())
print(q.get())
print('查看队列是否为空',q.empty())
print(q.get())#在多打一个get会形成程序阻塞
print('查看队列是否为空',q.empty())
try:
    q.get_nowait()#报错queue.Empty
except Exception:
    print('队列空了')
############################
当前队列内容长度 2
查看队列是否满了 True
1
2
查看队列是否为空 False
3
查看队列是否为空 True
队列空了
####先进后出 类似于栈
import queue
q = queue.LifoQueue(3)
#
q.put(1)
q.put(2)
q.put(3)
print(q.get())
print(q.get())
print(q.get())
##############
3
2
1
####优先级队列
import queue
q=queue.PriorityQueue(5)
q.put((5,'alex'))
q.put((2,'宝宝'))
q.put((4,'大力'))
print(q.get())
print(q.get())
print(q.get())
##########
(2, '宝宝')
(4, '大力')
(5, 'alex')
#如果优先级数字相同,如果数据类型不同会报错,类型相同会对比元祖中的第二行英语字母

3.线程池

map方法

import time
from concurrent.futures import ThreadPoolExecutor
from threading import current_thread

def func(n):
    time.sleep(1)
    print(n)
    # print(n,current_thread().ident)

if __name__ == '__main__':
    t_p = ThreadPoolExecutor(4)
    map_res = t_p.map(func,range(10))   #异步执行的,map自带join功能
    print(map_res)
    print([i for i in map_res])
#######################
<generator object Executor.map.<locals>.result_iterator at 0x00000000029E94F8>
012

3

4
5
6
7
89
[None, None, None, None, None, None, None, None, None, None]#会取不到值
concurrent.futures 写法
import time
from threading import current_thread
from concurrent.futures import  ThreadPoolExecutor,ProcessPoolExecutor
def func(n):
    time.sleep(0.1)#此处等待一秒是为了将取值时候的打印结果进行区分
    # print(n)
    return n
if __name__ == '__main__':
    t_p = ThreadPoolExecutor(4)#可以进行线程进程切换
    # t_p=ProcessPoolExecutor(4)
    t_res_lst = []
    for i in range(10):
        res_obj =t_p.submit(func,i)   #提交执行函数,返回一个结果对象,i作为任务函数的参数
        t_res_lst.append(res_obj)
    t_p.shutdown()  #起到原来的close阻止新任务进来 + join的作用,等待所有的线程执行完毕
    # print("t_res_lst",t_res_lst)      #<Future at 0x1fa10a43400 state=finished returned int> 加了shutdown后全部变为finished
                                      #<Future at 0x19d37f5c7f0 state=running>, <Future at 0x19d37f5c9b0 state=pending>不加shutdo时
    for e_res in t_res_lst:
        print(e_res.result())
    # t_p.shutdown()
#在不加shutdown时,主线程在循环列表时,也是每一个进行取值,
# 但是由于可以有四个对象可以一起取值,(拿前四个为例,)
# 也就是当列表循环到4个时此时会等待将近1s
# 因为在执行函数有停留,但线程池可以四个同时执行,因此会有4个结果一起出来
#但是当加了shutdown时,此时线程会全部执行完毕,然后在列表里是,此时的对象已经全部执行完毕
########################
0
1
2
3
4
5
6
7
8
9

4.协程

协程本质上就是一个线程,以前线程任务的切换是由操作系统控制的,遇到I/O自动切换,在我们自己的程序里面来控制任务的切换。
现在我们用协程的目的就是较少操作系统切换的开销(开关线程,创建寄存器、堆栈等,在他们之间进行切换等),

import gevent
from gevent import monkey;monkey.patch_all()#本身不认识其他模块中的IO操作,但是如果我们在导入其他模块之前执行 就能够认识
import time
import threading
def f1():
    print('第一次f1')
    # print(threading.current_thread().getName())
    # gevent.sleep(1)
    time.sleep(2)
    print('第二次f1')
def f2():
    # print(threading.current_thread().getName())
    print('第一次f2')
    # gevent.sleep(2)
    time.sleep(2)
    print('第二次f2')
s = time.time()
g1 = gevent.spawn(f1) #异步提交了f1任务
g2 = gevent.spawn(f2) #异步提交了f2任务
# g1.join()
# g2.join()
gevent.joinall([g1,g2])
e = time.time()
print('执行时间:',e-s)
print('主程序任务')
#######################
第一次f1
第一次f2
第二次f1
第二次f2
执行时间: 2.0021142959594727
主程序任务

下面是理解 :可看 可不看

#####生成器写法
import time
def f1():
    for i in range(2):
        time.sleep(0.5)
        print('f1>>',i)
        yield
def f2():
    g = f1()
    for i in range(2):
        time.sleep(0.5)
        print('f2>>', i)
        next(g)
f1()
f2()
############
f2>> 0
f1>> 0
f2>> 1
f1>> 1
#######greenlet模块
import time
from greenlet import greenlet
def f1(s):
    print('第一次f1'+s)
    g2.switch('taibai')  #切换到g2这个对象的任务去执行
    time.sleep(1)
    print('第二次f1'+s)
    g2.switch()
def f2(s):
    print('第一次f2'+s)
    g1.switch()
    time.sleep(1)
    print('第二次f2'+s)
g1 = greenlet(f1)  #实例化一个greenlet对象,并将任务名称作为参数参进去
g2 = greenlet(f2)
g1.switch('alex') #执行g1对象里面的任务
###########
#首先会执行g1的switch(alex)也就是执行f1 print('第一次f1'+alex)
#往下就会执行f2 进行传参taibai 会打印 第一次f2taibai
#往下 执行了g1也就是f1  print('第二次f1'+s)
#往下继续走  print('第二次f2'+taibai)
##########结果
第一次f1alex
第一次f2taibai
第二次f1alex
第二次f2taibai

 回调

猜你喜欢

转载自www.cnblogs.com/zaizai1573/p/10268691.html