day 34线程的其他方法,线程池
线程的其他方法:
from threading import Thread,current_thread:
currrent_thread().getName() 获取线程的名称
current_thread().ident 获取到线程的id
current_thread() 当前线程的信息
import threading #导入threading模块才能使用下面的功能:
threading.enumerate() 当前正在运行线程对象的列表
threading.active_count() 活动的线程
import time
import threading
from threading import Thread,current_thread
def f1(n):
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()) ###MainThread
print('主线程ID',current_thread().ident) ##2260
print(current_thread()) #当前线程<_MainThread(MainThread, started 2260)>
print(threading.enumerate()) #[<_MainThread(MainThread, started 2260)>, <Thread(Thread-1, started 2520)>] 当前正在运行线程对象的列表
print(threading.active_count()) # 活动的线程 #2
线程池(重点)
from concurrent.futures import ThreadPoolExecutor,ProcessPoolExecutor
p =ThreadPoolExecutor() 默认的线程个数是cpu个数 *5
p = ProcessPoolExecutor() 默认的进程个数是cup个数(核数)
p.map(f1, 可迭代的对象) 异步执行
def f1(n1,n2):
print(n1,n2)
p.submit(f1,11,12)
res=p.submit(f1,11,12)
异步提交任务,里面无敌传参,但是形参位置必须对应实参接收
res.result() 和get 方法一样,如果没有结果,会等待,阻塞程序
shutdown() close+join锁定线程池,等待线程池中所有已经提交的任务全部执行完毕
import time
from threading import current_thread
from concurrent.futures import ThreadPoolExecutor,ProcessPoolExecutor
def f1(n,s):
time.sleep(1)
# print('%s号子线程' %current_thread().ident)
# print(n,s)
return (n,s)
if __name__ == '__main__':
tp =ThreadPoolExecutor(4)
# tp = ProcessPoolExecutor(4)
# tp.map(f1,range(10)) #异步提交任务,参数同样是任务名称,可迭代对象
res_list = []
for i in range(10):
res = tp.submit(f1,i,'藤椒') #submit是给线程池异步提交任务
print(res)
#res.result()
res_list.append(res)
# for r in res_list:
# print(r.result())
tp.shutdown() #主线程等待所有提交给线程池的任务,全部执行完毕 close+join
for r in res_list:
print(r.result())
print('主线程结束')
队列(重点)
先进先出
queue.Queue() 先进先出队列
q.qsize() 当前内容的长度
q.full() 查看队列是否满了
q.empty() 查看队列是否空了
q.put_nowait() 放入不等待,程序往下执行
q.get_nowait() 获取不等待,程序往下执行
import queue
#先进先出队列
q =queue.Queue(3)
q.put(1)
q.put(2)
print('当前队列内容长度',q.qsize())
q.put(3)
print('查看队列是否满了',q.full())
try:
q.put_nowait(4) #报错queue.Full
except Exception:
print('队列满了')
print(q.get())
print(q.get())
print('查看队列是否为空',q.empty())
print(q.get())
print('查看队列是否为空',q.empty())
try:
q.get_nowait() #queue.Empty
except Exception:
print('队列空了')
先进后出,或者后进先出,类似于栈fifo: first in first out
queue.LifoQueue() 先进后出\后进先出队列
import queue
q = queue.LifoQueue(3)
q.put(1)
q.put(2)
q.put(3)
print(q.get())
print(q.get())
print(q.get())
优先队列:
queue.PriorityQueue()
put的数据是一个元组,元组的第一个参数是优先级数字,数字越下,优先级越高,越先被get到被去出来,第二个参数是put进去的值,吐过说优先级相同,那么直别忘了应该是相同的数据类型,字典不行
如果优先级数字相同,会比较第二个参数的元素的ascii表中的位置,如果数据类型不同会报错.
如果说值里面的元素是数字类型,那么两个值的优先级相同时,比较的是两个值得大小,小的优先被去出来.
import queue
q = queue.PriorityQueue(5)
# q.put((5,'alex'))
# q.put((2,'宝宝'))
# q.put((7,'大力'))
# q.put((5,(2,3)))
q.put((5,(2,3))) #如果说值里面的元素是数字类型,那么当两个值的优先级相同时,比较的是两个值的大小,小的优先被取出来
#如果元素是字符串,那么依次比较每个字母的ascii表中的位置,小的优先被取出来
# q.put((2,{'x':3}))
# q.put((5,(1,2)))
q.put((5,(2,2,3)))
# q.put((2,'zalex'))
# q.put((-1,'yubing'))
# q.put((2,{'k':666})) #如果优先级数字相同,如果数据类型不同会报错
# q.put((2,('a','b')))
# q.put((1,(1,2)))
# q.put((3,(1,2)))
# q.put((-10,(1,2)))
print(q.get())
协程:轻量型线程. 生成器,Greenlet模块,Gevent模块(重点)
协程:一个线程里面实现任务的并发:变成生成器(记录状态),实现两个程序的来回切换,实现并发
生成器版协程:
import time
def f1():
for i in range(10):
time.sleep(0.5)
print('f1>>',i)
yield
def f2():
g = f1()
for i in range(10):
time.sleep(0.5)
print('f2>>', i)
next(g)
f1()
f2()
Greenlet模块
如果导入模块报错,是没有加载第三方的模块,首先:在py解释器上找到Terminal输入:pip install greenlet,如果提示不是内部命令,找到python安装的位置的路径,Scripts文件里面的pip,选择路径,添加到环境变量里面(我的电脑--属性--高级系统设置--环境变量--Path新建添加),在使用管理员命令输入pip install greenlet,最后重启解释器就完成啦,可以开心的使用.
import time
import greenlet
from greenlet import greenlet
def f1(s):
print('第一次f1'+s)
g2.switch('taibai')
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)
g2 = greenlet(f2)
g1.switch('alex')
Gevent模块(重点)
import gevent
from gevent import monkey;monkey.patch_all()
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('主程序任务')
线程池的回调函数
from concurrent.futures import ThreadPoolExecutor,ProcessPoolExecutor
def f1(n,s):
return n+s
def f2(n):
print('回调函数>>>',n.result())
if __name__ == '__main__':
tp = ThreadPoolExecutor(4)
res = tp.submit(f1,11,12).add_done_callback(f2)
# print(res.result())
线程的其他方法:
from threading import Thread,current_thread:
currrent_thread().getName() 获取线程的名称
current_thread().ident 获取到线程的id
current_thread() 当前线程的信息
import threading #导入threading模块才能使用下面的功能:
threading.enumerate() 当前正在运行线程对象的列表
threading.active_count() 活动的线程
import time
import threading
from threading import Thread,current_thread
def f1(n):
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()) ###MainThread
print('主线程ID',current_thread().ident) ##2260
print(current_thread()) #当前线程<_MainThread(MainThread, started 2260)>
print(threading.enumerate()) #[<_MainThread(MainThread, started 2260)>, <Thread(Thread-1, started 2520)>] 当前正在运行线程对象的列表
print(threading.active_count()) # 活动的线程 #2
线程池(重点)
from concurrent.futures import ThreadPoolExecutor,ProcessPoolExecutor
p =ThreadPoolExecutor() 默认的线程个数是cpu个数 *5
p = ProcessPoolExecutor() 默认的进程个数是cup个数(核数)
p.map(f1, 可迭代的对象) 异步执行
def f1(n1,n2):
print(n1,n2)
p.submit(f1,11,12)
res=p.submit(f1,11,12)
异步提交任务,里面无敌传参,但是形参位置必须对应实参接收
res.result() 和get 方法一样,如果没有结果,会等待,阻塞程序
shutdown() close+join锁定线程池,等待线程池中所有已经提交的任务全部执行完毕
import time
from threading import current_thread
from concurrent.futures import ThreadPoolExecutor,ProcessPoolExecutor
def f1(n,s):
time.sleep(1)
# print('%s号子线程' %current_thread().ident)
# print(n,s)
return (n,s)
if __name__ == '__main__':
tp =ThreadPoolExecutor(4)
# tp = ProcessPoolExecutor(4)
# tp.map(f1,range(10)) #异步提交任务,参数同样是任务名称,可迭代对象
res_list = []
for i in range(10):
res = tp.submit(f1,i,'藤椒') #submit是给线程池异步提交任务
print(res)
#res.result()
res_list.append(res)
# for r in res_list:
# print(r.result())
tp.shutdown() #主线程等待所有提交给线程池的任务,全部执行完毕 close+join
for r in res_list:
print(r.result())
print('主线程结束')
队列(重点)
先进先出
queue.Queue() 先进先出队列
q.qsize() 当前内容的长度
q.full() 查看队列是否满了
q.empty() 查看队列是否空了
q.put_nowait() 放入不等待,程序往下执行
q.get_nowait() 获取不等待,程序往下执行
import queue
#先进先出队列
q =queue.Queue(3)
q.put(1)
q.put(2)
print('当前队列内容长度',q.qsize())
q.put(3)
print('查看队列是否满了',q.full())
try:
q.put_nowait(4) #报错queue.Full
except Exception:
print('队列满了')
print(q.get())
print(q.get())
print('查看队列是否为空',q.empty())
print(q.get())
print('查看队列是否为空',q.empty())
try:
q.get_nowait() #queue.Empty
except Exception:
print('队列空了')
先进后出,或者后进先出,类似于栈fifo: first in first out
queue.LifoQueue() 先进后出\后进先出队列
import queue
q = queue.LifoQueue(3)
q.put(1)
q.put(2)
q.put(3)
print(q.get())
print(q.get())
print(q.get())
优先队列:
queue.PriorityQueue()
put的数据是一个元组,元组的第一个参数是优先级数字,数字越下,优先级越高,越先被get到被去出来,第二个参数是put进去的值,吐过说优先级相同,那么直别忘了应该是相同的数据类型,字典不行
如果优先级数字相同,会比较第二个参数的元素的ascii表中的位置,如果数据类型不同会报错.
如果说值里面的元素是数字类型,那么两个值的优先级相同时,比较的是两个值得大小,小的优先被去出来.
import queue
q = queue.PriorityQueue(5)
# q.put((5,'alex'))
# q.put((2,'宝宝'))
# q.put((7,'大力'))
# q.put((5,(2,3)))
q.put((5,(2,3))) #如果说值里面的元素是数字类型,那么当两个值的优先级相同时,比较的是两个值的大小,小的优先被取出来
#如果元素是字符串,那么依次比较每个字母的ascii表中的位置,小的优先被取出来
# q.put((2,{'x':3}))
# q.put((5,(1,2)))
q.put((5,(2,2,3)))
# q.put((2,'zalex'))
# q.put((-1,'yubing'))
# q.put((2,{'k':666})) #如果优先级数字相同,如果数据类型不同会报错
# q.put((2,('a','b')))
# q.put((1,(1,2)))
# q.put((3,(1,2)))
# q.put((-10,(1,2)))
print(q.get())
协程:轻量型线程. 生成器,Greenlet模块,Gevent模块(重点)
协程:一个线程里面实现任务的并发:变成生成器(记录状态),实现两个程序的来回切换,实现并发
生成器版协程:
import time
def f1():
for i in range(10):
time.sleep(0.5)
print('f1>>',i)
yield
def f2():
g = f1()
for i in range(10):
time.sleep(0.5)
print('f2>>', i)
next(g)
f1()
f2()
Greenlet模块
如果导入模块报错,是没有加载第三方的模块,首先:在py解释器上找到Terminal输入:pip install greenlet,如果提示不是内部命令,找到python安装的位置的路径,Scripts文件里面的pip,选择路径,添加到环境变量里面(我的电脑--属性--高级系统设置--环境变量--Path新建添加),在使用管理员命令输入pip install greenlet,最后重启解释器就完成啦,可以开心的使用.
import time
import greenlet
from greenlet import greenlet
def f1(s):
print('第一次f1'+s)
g2.switch('taibai')
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)
g2 = greenlet(f2)
g1.switch('alex')
Gevent模块(重点)
import gevent
from gevent import monkey;monkey.patch_all()
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('主程序任务')
线程池的回调函数
from concurrent.futures import ThreadPoolExecutor,ProcessPoolExecutor
def f1(n,s):
return n+s
def f2(n):
print('回调函数>>>',n.result())
if __name__ == '__main__':
tp = ThreadPoolExecutor(4)
res = tp.submit(f1,11,12).add_done_callback(f2)
# print(res.result())