python程序多线程_Python-多线程编程
threading模塊
threading 模塊的對象
對 象描 述
Thread
表示一個執行線程的對象
Lock
鎖原語對象(和 thread 模塊中的鎖一樣)
RLock
可重入鎖對象,使單一線程可以(再次)獲得已持有的鎖(遞歸鎖)
Condition
條件變量對象,使得一個線程等待另一個線程滿足特定的“條件”,比如改變狀態或 某個數據值
Event
條件變量的通用版本,任意數量的線程等待某個事件的發生,在該事件發生后所有 線程將被激活
Semaphore
為線程間共享的有限資源提供了一個“計數器”,如果沒有可用資源時會被阻塞
BoundedSemaphore
與 Semaphore 相似,不過它不允許超過初始值
Timer
與 Thread 相似,不過它要在運行前等待一段時間
Barrier①
創建一個“障礙”,必須達到指定數量的線程后才可以繼續
守護線程
thread模塊,不支持守護線程這個概念。
當主線程退出時,所有子線程都將終止,不管它們是否仍在工作
如果你不希望發生這種行為,就要引入守護線程的概念了
threading 模塊支持守護線程,其工作方式是:守護線程一般是一個等待客戶端請求服務的服務器。
如果沒有客戶端請求,守護線程就是空閑的。
如果把一個線程設置為守護線程,就表示這個線程是不重要的,進程退出時不需要等待這個線程執行完成。
要將一個線程設置為守護線程,需要在啟動線程之前執行如下賦值語句:thread.daemon = True
同樣,要檢查線程的守護狀態,也只需要檢查這個值即可,一個新的子線程會繼承父線程的守護標記。
整個 Python 程序(主線程)將在所有非守護線程退出之后才退出
換句話說,就是沒有剩下存活的非守護線程時。
Thread 類
threading 模塊的 Thread 類是主要的執行對象。它有 thread 模塊中沒有的很多函數。
Thread
對象的屬性和方法
屬 性描 述
Thread 對象數據屬性
name
線程名
ident
線程的標識符
daemon
布爾標志,表示這個線程是否是守護線程
Thread 對象方法
init(group=None, tatget=None, name=None, args=(), kwargs ={}, verbose=None, daemon=None) ③
實例化一個線程對象,需要有一個可調用的 target,以及其參數 args 或 kwargs。還可以傳遞 name 或 group 參數,不過后者還未實現。此 外 , verbose 標 志 也 是 可 接 受 的。 而 daemon 的 值 將 會 設定 thread.daemon 屬性/標志
屬 性描 述
start()
開始執行該線程
run()
定義線程功能的方法(通常在子類中被應用開發者重寫)
join (timeout=None)
直至啟動的線程終止之前一直掛起;除非給出了 timeout(秒),否則 會一直阻塞
getName()①
返回線程名
setName (name)①
設定線程名
isAlivel /is_alive ()②
布爾標志,表示這個線程是否還存活
isDaemon()③
如果是守護線程,則返回 True;否則,返回 False
setDaemon(daemonic)③
把線程的守護標志設定為布爾值 daemonic(必須在線程 start()之前 調用)
創建實例
啟動一個線程就是把一個函數傳入并創建Thread實例,然后調用start()開始執行
#!/usr/bin/env python
#-*- coding:utf8 -*-import threading
import time
def loop():
strat_time=time.time()
print('thread %s is running...' %threading.current_thread().name) #當前進程名
n= 0
while n < 5:
n= n + 1print('thread %s >>> %s' %(threading.current_thread().name, n))
time.sleep(1)
print('thread %s ended.' %threading.current_thread().name)
end_time=time.time()
all_time= end_time -strat_time
print("共用時:%s" %all_time)
print('thread %s is running...time = %s' %(threading.current_thread().name,time.ctime()))
t= threading.Thread(target=loop, name='LoopThread') # 創建Thread實例
t.start() # 開始執行
t.join() # 阻塞主線程
print('thread %s ended. time = %s' % (threading.current_thread().name,time.ctime()))
多線程和多進程最大的不同在于,多進程中,同一個變量,各自有一份拷貝存在于每個進程中,互不影響,Lock
而多線程中,所有變量都由所有線程共享,所以,任何一個變量都可以被任何一個線程修改,
因此,線程之間共享數據最大的危險在于多個線程同時改一個變量,把內容給改亂了。
一個用Lock解決的示例代碼
import time, threading
# 假定這是你的銀行存款:
balance= 0
lock=threading.Lock() #創建鎖
def change_it(n):
# 先存后取,結果應該為0:globalbalance
balance= balance +n
balance= balance -n
def run_thread(n):for i in range(100000):lock.acquire() # 申請鎖try:
change_it(n)finally:lock.release() # 釋放鎖
t1= threading.Thread(target=run_thread, args=(5,))
t2= threading.Thread(target=run_thread, args=(8,))
t1.start()
t2.start()
t1.join()
t2.join()
print("The Res is %d" % balance)
queue模塊,提供線程間通信的機制,從而讓線程之間可以互相分享數據生產者-消費者問題和queue模塊
具體而言,就是創建一個隊列,讓生產者(線程)在其中放入新的商品,而消費者(線程)消費這些商品
queue
模塊常用屬性
屬 性描 述
queue 模塊的類
Queue(maxsize=0)
創建一個先入先出隊列。如果給定最大值,則在隊列沒有空間時阻塞;否則(沒 有指定最大值),為無限隊列
LifoQueue(maxsize=0)
創建一個后入先出隊列。如果給定最大值,則在隊列沒有空間時阻塞;否則(沒 有指定最大值),為無限隊列
PriorityQueue(maxsize=0)
創建一個優先級隊列。如果給定最大值,則在隊列沒有空間時阻塞,否則(沒 有指定最大值) ,為無限隊列
Queue/queue 異常
Empty
當對空隊列調用 get*()方法時拋出異常
Full
當對已滿的隊列調用 put*()方法時拋出異常
Queue/queue 對象方法
qsize ()
返回隊列大小(由于返回時隊列大小可能被其他線程修改,所以該值為近似值)
empty()
如果隊列為空,則返回 True;否則,返回 False
full()
如果隊列已滿,則返回 True;否則,返回 False
put (item, block=Ture, timeout=None)
將 item 放入隊列。如果 block 為 True(默認)且 timeout 為 None,則在有可用 空間之前阻塞;如果 timeout 為正值,則最多阻塞 timeout 秒;如果 block 為 False, 則拋出 Empty 異常
put_nowait(item)
和 put(item, False)相同
get (block=True, timeout=None)
從隊列中取得元素。如果給定了 block(非 0),則一直阻塞到有可用的元素 為止
get_nowait()
和 get(False)相同
task_done()
用于表示隊列中的某個元素已執行完成,該方法會被下面的 join()使用
join()
在隊列中所有元素執行完畢并調用上面的 task_done()信號之前,保持阻塞
MyThread.py
#!/usr/bin/env python
import threadingfromtime import ctimeclassMyThread(threading.Thread):
def __init__(self, func, args, name=''):
threading.Thread.__init__(self)
self.func=func
self.name=name
self.args=args
def run(self):
print('開始執行', self.name, '在:', ctime())
self.res= self.func(*self.args)
print(self.name,'結束于:', ctime())
def getResult(self):return self.res
product.py
#!/usr/bin/env python
#-*- coding:utf8 -*-
fromrandom import randintfromtime import sleepfromqueue import QueuefromMyThread import MyThread
# 將一個對象放入隊列中
def writeQ(queue):
print('正在為隊列生產………')
queue.put('商品', 1)
print('當前商品總數:', queue.qsize())
# 消費隊列中的一個對象
def readQ(queue):
val= queue.get(1)
print('正在從隊列中消費商品……消費后還剩余商品:', queue.qsize())
# 模仿生產者。
def writer(queue, loops):for i inrange(loops):
writeQ(queue)
sleep(randint(1, 3)) # writer的睡眠時間一般比reader短,是為了阻礙 reader從空隊列中獲取對象,換句話說就是使得輪到reader執行時,已存在可消費對象的可能性更大。
# 模仿消費者
def reader(queue, loops):for i inrange(loops):
readQ(queue)
sleep(randint(2, 5))
funcs=[writer, reader]
nfuncs=range(len(funcs))
def main():
nloops= randint(2, 5) # randint 和randrange類似,區別在于,randrange是半開半閉區間,而randint是閉區間
q= Queue(32)
threads=[] # 模擬線程池for i innfuncs:
t=MyThread(funcs[i], (q, nloops), funcs[i].__name__) # 創建線程
threads.append(t)for i innfuncs:
threads[i].start() # 開始執行線程for i innfuncs:
threads[i].join()
print('結束')if __name__ == '__main__':
main()
總結
以上是生活随笔為你收集整理的python程序多线程_Python-多线程编程的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: python网格搜索核函数_机器学习笔记
- 下一篇: 定时器回调函数怎么写_ESP8266_0