1. 程式人生 > >(三十四)線程的隊列

(三十四)線程的隊列

取數 elf https tom thread ocs cpu mon sta

一、線程的其他方法

1.threading.current_thread()獲取對象可以使用的方法
def fn():
    pass
t = Thread(target=fn,)
t.start()
obj = threading.current_thread()
print(obj.getName(), obj.name)
print(obj.ident)

  2.threading直接可以使用的方法

print(threading.enumerate())#獲取當前活躍的線程的列表
print(threading.active_count())#獲取當前活躍的線程的總數

  

二、線程隊列

  1. 普通隊列
import queue
q = queue.Queue(5)#不給數量,這個隊列就是無限大的
q.put(1)
q.put(2)
q.put(3)
q.put(4)
q.put(5)
#print(q.full())#判斷隊列是否已滿,不過有時不太準確
#print(q.qsize())#獲取隊列中元素的的數量,其實這個方法裏面裏面也是使用的len()函數
try:
    # q.put(6)#如果隊列裝滿了,會一直停留在這裏
    q.put_nowait(6)#如果隊列滿了,會報錯,使用try後,可以抓取異常,然後繼續向下執行
except Exception:
    print(‘zhe queue is full‘)
#print(q.empty())#查看隊列是否已空,不過有時不太準確
print(q.get())
print(q.get())
print(q.get())
print(q.get())
print(q.get())
try:
    print(q.get())
except Exception:
    print(‘zhe queue is empty‘)

  

2.LifoQueue--先進後出隊列,獲取順序類似棧

這就是一個繼承了Queue的列表,其他的方法就是繼承於Queue

q = queue.LifoQueue(3)
q.put(1)#添加數據就是向列表裏append()數據
q.put(2)
q.put(3)

print(q.get())#就是使用pop()刪除列表
print(q.get())
print(q.get())
結果:
3
2
1

  

第一步初始化一個列表:

def _init(self, maxsize):
    self.queue = []

  

第二步添加數據:

def _put(self, item):
    self.queue.append(item)

  

第三部刪除數據:

def _get(self):
    return self.queue.pop()

  

3.PriorityQueue--優先級隊列

q = queue.PriorityQueue()
q.put((3,‘4‘))
q.put((2,3))
q.put((1,‘d‘))
q.put((5,‘s‘))
q.put((4,‘w‘))

print(q.get())
print(q.get())
print(q.get())
print(q.get())
print(q.get())
結果:
(1, ‘d‘)
(2, 3)
(3, ‘4‘)
(4, ‘w‘)
(5, ‘s‘)

  

結果按照元組中第一個元素的ASCII碼的升序排序後輸出,如果第一元素相等,就按照第二個元素的ASCII碼的升序排列,以此類推。但是,字典元素不可比較。相對應比較的兩個元素必須是同類型的。

優先級隊列也是一個列表:

def _init(self, maxsize):
    self.queue = []

  

就是增加和獲取時,與列表有些區別。

三、線程池

  1. ThreadPoolExecutor

(1) map

def f(n):
    time.sleep(0.5)
    print(n)
t = ThreadPoolExecutor(4)  # 默認數量是,CPU個數的5倍
t.map(f, range(10))

  

(2)submit()

def f(n):
    time.sleep(0.3)
    # print(n)
    return n**2
Def fn(m):
Print(m)
t = ThreadPoolExecutor(4)  # 默認數量是,CPU個數的5倍
t_lst = []
for i in range(10):
    #功能後面的參數是無敵傳參,*args,**kwargs,傳遞實參的個數不限制,但是形參的個數與形式也要跟實參的一一對應上
    res = t.submit(f, n=i)
#t.submit()..add_done_callback(fn)#回調函數

    #print(res)#返回的是結果對象
    # print(res.result())#這也是一個不拿到結果,誓不罷休的方法
    t_lst.append(res)

# for th in t_lst:#在shutdown()之前是每四個一次顯示出來
#     print(th.result())

# 相當於進程池的close()和join()兩個方法,其實裏面是讓每個線程都調用了join().
t.shutdown()

for th in t_lst:#會一下子展示出來數據
    print(th.result())

  

2.ProcessPoolExecutor

ThreadPoolExcutor的使用方法一樣大的。

四、協程

協程是線程裏最小的執行單元。首先得下載兩個模塊--greenletgevent

  1. greenlet

from greenleet import greenlet

def f1():
    print(‘f1---1111‘)
    g2.switch()
    print(‘f1---2222‘)
def f2():
    print(‘f2---1111‘)
    g1.switch()

g1 = greenlet(f1)
g2 = greenlet(f2)
g1.switch()

結果:
f1---1111
f2---1111
f1---2222

def f1(c):
    print(‘f1---1111‘,c)
    g2.switch(‘Tom‘)
    print(‘f1---2222‘,c)
def f2(c):
    print(‘f2---1111‘,c)
    g1.switch()#此處也可以添加參數,結果和現在就不一樣了,可以試試看
g1 = greenlet(f1)
g2 = greenlet(f2)
g1.switch(‘TOM‘)
結果:
f1---1111 TOM
f2---1111 Tom
f1---2222 TOM

  

greenlet利用switch切換,執行不同代碼塊的功能。

2.gevent

def f1():
    print(‘f1---11111‘)
    gevent.sleep(1)
#time.sleep(1)
    print(‘f1---22222‘)

def f2():
    print(‘f2---11111‘)
    gevent.sleep(2)
#time.sleep(1)
    print(‘f2---2222‘)
    
g1 = gevent.spawn(f1)
g2 = gevent.spawn(f2)

g1.join()#需要有
g2.join()
#gevent.joinall([g1,g2])#相當於上面的兩個一起

  

gevent只識別自己的sleep()time.sleep()不能被識別。為了類似time.sleep()這樣的阻塞被識別(還有input(),打開文件,讀取數據等),使用下面的方式:

from gevent import monkey; monkey.patch_all()

  

Python查看API:https://docs.python.org/3.7/library/os.html

  

(三十四)線程的隊列