1、线程的其他方法

 
Threading.current_thread() # 当前线程对象
getName()  获取线程名
Ident  获取线程id
Threading.Enumerate()  # 返回当前正在运行的线程对象的一个列表
Threading.active_count() 当前正在运行的线程数量
import threading
import time
from threading import Thread,current_thread

def f1(n):
    time.sleep(1)
    print('子线程名称',current_thread().getName())  # Thread-1
    print(f"{n}号线程任务")

if __name__ == '__main__':
    t1 = Thread(target=f1,args=(1,))
    t1.start()
    print('主线程的名称:',current_thread().getName())  # MainThread
    print('主线程的id',current_thread().ident)  
    print(current_thread())  # <_MainThread(MainThread, started 11088)>
    print(threading.enumerate())  # [<_MainThread(MainThread, started 11088)>, <Thread(Thread-1, started 9176)>]
    print(threading.active_count())
2、线程队列:(重点)
import queue
先进先出队列:queue.Queue(3)
import queue
q = queue.Queue(3)  # 先进先出
#fifo first in first out
q.put(1)
q.put(2)
print('当前队列内容长度:',q.qsize())
q.put(3)
print('查看队列是否满了:',q.full())
try:
    q.put_nowait(4)
except Exception:
    print('队列满了')
print(q.get())
print(q.get())
print('产看队列是否空:',q.empty())
print(q.get())
try:
    q.get_nowait()
except Exception:
    print('队列空了')
例子
# 二先进后出,或者后进先出,类似于栈
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.LifoQueue(3)
# 优先级队列
q = queue.PriorityQueue(5)
q.put((4,'zhouxiao'))
q.put((3,[1,2,3]))
q.put((3,[3,4,5]))
q.put((8,{'x':44}))
q.put((2,(4,7,)))
# 如果说值里面的元素是数字类型,那么当两个值的优先级相同时,比较的是两个值的大小,小的优先被取出来
# 如果元素是字符串,那么一次比较字母的ascii表总的位置,小的优先被取出
# 如果优先级数字相同,数据类型不一致会报错
print(q.get())
print(q.get())
print(q.get())
print(q.get())
print(q.get())
print(q.get())

结果:
(2, (4, 7))
(3, [1, 2, 3])
(3, [3, 4, 5])
(4, 'zhouxiao')
(8, {'x': 44})
优先级队列:queue.priorityQueue(3)
 
 put 的数据是一个元组,元组的第一个参数是优先级数字,数字越小优先级越高,越先被get到被取出来,第二个参数是put进去的值,如果优先级相同,后边的值应该是相同的数据类型
 
3、线程池:
concurrent.futures  模块提供了高度封装的异步调用接口
ThreadPoolExecutor  :线程池,提供异步调用
ProcessPoolExecutor :进程池,提供异步调用
 
from concurrent_futures  import ThreadPoolExecutor,ProcessPoolExecutor
 
p = ThreadPoolExecutor(4)  # 默认的线程个数是cpu个数*5
p = ProcessPoolExecutor(4) # 默认的进程个数是cpu个数
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(f"{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,'xiaoeng')
        # 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('主线程结束')
import time
import os
import threading
from concurrent.futures import ThreadPoolExecutor,ProcessPoolExecutor

def func(n):
    time.sleep(2)
    print('%s打印的:'%(threading.get_ident()),n)
    return n*n
tp = ThreadPoolExecutor(max_workers = 5) # 默认一般线程的数据不超过cpu个数*5
# tp = ProcessPoolExecutor(max_workers=5) # 进程池的使用只需要将上面的ThresdPoolExecutor 改为ProcessPoolExecutor就行了,其他的不用改
#  异步执行
t_list = []
for i in range(5):
    t = tp.submit(func,i) # 提交执行函数,返回一个结果对象,i作为任务函数的参数 def submit(self,fn,*args,**kwargs):可以传任意形式的参数
    t_list.append(t)
    print(t.result())
    # 这个返回的结果对象t,不能直接去拿结果,不然会又变成串行,可以理解为拿到一个号码,等所有线程的结果都出来之后,我们再去通过结果对象t获取结果

tp.shutdown() # 起到原来的close阻止新任务进来 + join的作用,等待所有线程执行完毕
print('主线程')
for t in t_list:
    print('>>>>',t.result())

# # 也可以不用shutdown()。用下面的这种方式
# while 1:
#     for n,t in enumerate(t_list):
#         print('>>>>',t.result())
#     time.sleep(2) # 每个两秒去取一次结果,哪个有结果了,就可以取出哪一个,想表达的意思就是说不用等到所有的结果都出来再去取,可以轮着去取结果,因为任务需要执行的时间很长,那么将会等很久才能拿到结果,通过这样的方式可以将快速出来的结果先拿出来,如果有的结果对象里面还没有执行结果,那么将什么也取不到,这一点要注意,不是空的,是什么也取不到,可以通过enumerate来判断我们已经取出了那个结果,记录你是哪一个位置的结果对象的结果已经被取过,取过的就不再取了。
#
# # 结果分析:打印的结果是没有顺序的,因为到了func函数中的sleep的时候,线程会切换,谁先打印就没准了,但是最后的我们通过结果对象取结果的时候拿到的是有序的,因为我们主线程进行for循环的时候,我们是按照顺序将结果对象添加到列表中

map的使用

from concurrent.futures import ThreadPoolExecutor,ProcessPoolExecutor
import threading
import os,time,random
def task(n):
    print(f"{threading.get_ident()} is runing")
    time.sleep(random.randint(1,3))
    return n**2

if __name__ == '__main__':
    executor=ThreadPoolExecutor(max_workers=3)

    # for i in range(11):
    #     future=executor.submit(task,i)

    s = executor.map(task,range(1,5)) # map取代了for+submit
    print([i for i in s])

回调函数简单应用

import os,time
import threading
from concurrent.futures import ThreadPoolExecutor,ProcessPoolExecutor

def func1(n):
    time.sleep(2)
    return n*n

def func2(m):
    print('func2结果为:%s'%(m.result()))

tp = ThreadPoolExecutor(max_workers=5)
t_list = []
for i in range(5):
    t = tp.submit(func1,i).add_done_callback(func2)

 

import time
from threading import current_thread
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)

回调函数的应用,

from concurrent.futures import ThreadPoolExecutor,ProcessPoolExecutor
from multiprocessing import Pool
import requests
import json
import os

def get_page(url):
    print('<进程%s> get %s' %(os.getpid(),url))
    respone =requests.get(url)
    if respone.status_code== 200:
        return {'url':url,'text':respone.text}
def parse_page(res):
    res = res.result()
    print('<%s> parse %s'%(os.getpid(),res['url']))
    parse_res='url:<%s> size:[%s]\n'%(res['url'],len(res['text']))
    with open('db.txt','a') as f:
        f.write(parse_res)

if __name__ == '__main__':
    urls=[
        'https://www.baidu.com';;,
        'https://www.python.org';;,
        'https://www.openstack.org';;,
        'https://help.github.com/';;,
        'http://www.sina.com.cn/';;
    ]

    # p = Pool(3)
    # for url in urls:
    #     p.apply_async(get_page,args=(url,),callback=pasrse_page)
    #  p.close()
    # p.join()

    p=ProcessPoolExecutor(3)
    for url in urls:
        p.submit(get_page,url).add_done_callback(parse_page)
        # parse_page 拿到的是一个future对象obj,需要obj.result()拿到结果

 

posted on 2019-01-14 22:00  古鲁月  阅读(93)  评论(0编辑  收藏  举报