目錄
創(chuàng)新互聯(lián)專注于青浦企業(yè)網(wǎng)站建設(shè),響應式網(wǎng)站設(shè)計,商城系統(tǒng)網(wǎng)站開發(fā)。青浦網(wǎng)站建設(shè)公司,為青浦等地區(qū)提供建站服務。全流程按需求定制制作,專業(yè)設(shè)計,全程項目跟蹤,創(chuàng)新互聯(lián)專業(yè)和態(tài)度為您提供的服務
眾所周知,CPU是計算機的核心,它承擔了所有的計算任務。而操作系統(tǒng)是計算機的管理者,是一個大管家,它負責任務的調(diào)度,資源的分配和管理,統(tǒng)領(lǐng)整個計算機硬件。應用程序是具有某種功能的程序,程序運行與操作系統(tǒng)之上
在很早的時候計算機并沒有線程這個概念,但是隨著時代的發(fā)展,只用進程來處理程序出現(xiàn)很多的不足。如當一個進程堵塞時,整個程序會停止在堵塞處,并且如果頻繁的切換進程,會浪費系統(tǒng)資源。所以線程出現(xiàn)了
線程是能擁有資源和獨立運行的最小單位,也是程序執(zhí)行的最小單位。一個進程可以擁有多個線程,而且屬于同一個進程的多個線程間會共享該進行的資源
① 200 多本 Python 電子書(和經(jīng)典的書籍)應該有
② Python標準庫資料(最全中文版)
③ 項目源碼(四五十個有趣且可靠的練手項目及源碼)
④ Python基礎(chǔ)入門、爬蟲、網(wǎng)絡開發(fā)、大數(shù)據(jù)分析方面的視頻(適合小白學習)
⑤ Python學習路線圖(告別不入流的學習)
私信我01即可獲取大量Python學習資源
進程時一個具有一定功能的程序在一個數(shù)據(jù)集上的一次動態(tài)執(zhí)行過程。進程由程序,數(shù)據(jù)集合和進程控制塊三部分組成。程序用于描述進程要完成的功能,是控制進程執(zhí)行的指令集;數(shù)據(jù)集合是程序在執(zhí)行時需要的數(shù)據(jù)和工作區(qū);程序控制塊(PCB)包含程序的描述信息和控制信息,是進程存在的唯一標志
在Python中,通過兩個標準庫 thread 和 Threading 提供對線程的支持, threading 對 thread 進行了封裝。 threading 模塊中提供了 Thread , Lock , RLOCK , Condition 等組件
在Python中線程和進程的使用就是通過 Thread 這個類。這個類在我們的 thread 和 threading 模塊中。我們一般通過 threading 導入
默認情況下,只要在解釋器中,如果沒有報錯,則說明線程可用
守護模式:
現(xiàn)在我們程序代碼中,有多個線程, 并且在這個幾個線程中都會去 操作同一部分內(nèi)容,那么如何實現(xiàn)這些數(shù)據(jù)的共享呢?
這時,可以使用 threading庫里面的鎖對象 Lock 去保護
Lock 對象的acquire方法 是申請鎖
每個線程在操作共享數(shù)據(jù)對象之前,都應該申請獲取操作權(quán),也就是調(diào)用該共享數(shù)據(jù)對象對應的鎖對象的acquire方法,如果線程A 執(zhí)行了 acquire() 方法,別的線程B 已經(jīng)申請到了這個鎖, 并且還沒有釋放,那么 線程A的代碼就在此處 等待 線程B 釋放鎖,不去執(zhí)行后面的代碼。
直到線程B 執(zhí)行了鎖的 release 方法釋放了這個鎖, 線程A 才可以獲取這個鎖,就可以執(zhí)行下面的代碼了
如:
到在使用多線程時,如果數(shù)據(jù)出現(xiàn)和自己預期不符的問題,就可以考慮是否是共享的數(shù)據(jù)被調(diào)用覆蓋的問題
使用 threading 庫里面的鎖對象 Lock 去保護
Python中的多進程是通過multiprocessing包來實現(xiàn)的,和多線程的threading.Thread差不多,它可以利用multiprocessing.Process對象來創(chuàng)建一個進程對象。這個進程對象的方法和線程對象的方法差不多也有start(), run(), join()等方法,其中有一個方法不同Thread線程對象中的守護線程方法是setDeamon,而Process進程對象的守護進程是通過設(shè)置daemon屬性來完成的
守護模式:
其使用方法和線程的那個 Lock 使用方法類似
Manager的作用是提供多進程共享的全局變量,Manager()方法會返回一個對象,該對象控制著一個服務進程,該進程中保存的對象運行其他進程使用代理進行操作
語法:
線程池的基類是 concurrent.futures 模塊中的 Executor , Executor 提供了兩個子類,即 ThreadPoolExecutor 和 ProcessPoolExecutor ,其中 ThreadPoolExecutor 用于創(chuàng)建線程池,而 ProcessPoolExecutor 用于創(chuàng)建進程池
如果使用線程池/進程池來管理并發(fā)編程,那么只要將相應的 task 函數(shù)提交給線程池/進程池,剩下的事情就由線程池/進程池來搞定
Exectuor 提供了如下常用方法:
程序?qū)?task 函數(shù)提交(submit)給線程池后,submit 方法會返回一個 Future 對象,F(xiàn)uture 類主要用于獲取線程任務函數(shù)的返回值。由于線程任務會在新線程中以異步方式執(zhí)行,因此,線程執(zhí)行的函數(shù)相當于一個“將來完成”的任務,所以 Python 使用 Future 來代表
Future 提供了如下方法:
使用線程池來執(zhí)行線程任務的步驟如下:
最佳線程數(shù)目 = ((線程等待時間+線程CPU時間)/線程CPU時間 )* CPU數(shù)目
也可以低于 CPU 核心數(shù)
使用線程池來執(zhí)行線程任務的步驟如下:
關(guān)于進程的開啟代碼一定要放在 if __name__ == '__main__': 代碼之下,不能放到函數(shù)中或其他地方
開啟進程的技巧
開啟進程的數(shù)量最好低于最大 CPU 核心數(shù)
# -*- coding: utf-8 -*-import threadingimport threadimport time class Test(object): def __init__(self): # threading.Thread.__init__(self) self._sName = "machao" def process(self): #args是關(guān)鍵字參數(shù),需要加上名字,寫成args=(self,) th1 = threading.Thread(target=Test.buildList, args=(self,)) th1.start() th1.join() def buildList(self): while True: print "start" time.sleep(3) test = Test()test.process()
# -*- coding: utf-8 -*-
import threading
import thread
import time
class Test(object):
def __init__(self):
# threading.Thread.__init__(self)
self._sName = "machao"
def process(self):
#args是關(guān)鍵字參數(shù),需要加上名字,寫成args=(self,)
th1 = threading.Thread(target=Test.buildList, args=(self,))
th1.start()
th1.join()
def buildList(self):
while True:
print "start"
time.sleep(3)
test = Test()
test.process()
將你需要多線程并發(fā)執(zhí)行的函數(shù)放入list中
import threading
threads = []
t1 = threading.Thread(target=函數(shù)名,args=參數(shù))
threads.append(t1)
啟動多線程
if __name__ == '__main__':
??? for t in threads:
? ? ??? t.setDaemon(True)
? ? ??? t.start()
t.join()
更多詳細操作help(threading)
#coding=utf-8
import?threading
from?time?import?ctime,sleep
#?要啟動的函數(shù)
def?music(func):
for?i?in?range(2):
print?"I?was?listening?to?%s.?%s"?%(func,ctime())
sleep(1)
#?要啟動的函數(shù)
def?move(func):
for?i?in?range(2):
print?"I?was?at?the?%s!?%s"?%(func,ctime())
sleep(5)
threads?=?[]
t1?=?threading.Thread(target=music,args=(u'愛情買賣',))
threads.append(t1)
t2?=?threading.Thread(target=move,args=(u'阿凡達',))
threads.append(t2)
#?函數(shù)加入線程列表
if?__name__?==?'__main__':
for?t?in?threads:
t.setDaemon(True)
t.start()
t.join()?#子線程完成運行之前,這個子線程的父線程將一直被阻塞,不會退出
print?"all?over?%s"?%ctime()
1.python中數(shù)據(jù)類型,int,float,復數(shù),字符,元組,做全局變量時需要在函數(shù)里面用global申明變量,才能對變量進行操作。
而,對象,列表,詞典,不需要聲明,直接就是全局的。
2.線程鎖mutex=threading.Lock()
創(chuàng)建后就是全局的。線程調(diào)用函數(shù)可以直接在函數(shù)中使用。
mutex.acquire()開啟鎖
mutex=release()關(guān)閉鎖
要注意,死鎖的情況發(fā)生。
注意運行效率的變化:
正常1秒,完成56997921
加鎖之后,1秒只運行了531187,相差10倍多。
3.繼承.threading.Thread的類,無法調(diào)用__init__函數(shù),無法在創(chuàng)建對象時初始化新建的屬性。
4.線程在cpu的執(zhí)行,有隨機性
5. 新建線程時,需要傳參數(shù)時,args是一個元組,如果只有一個參數(shù),一定后面要加一個,符號。不能只有一個參數(shù)否則線程會報創(chuàng)建參數(shù)錯誤。threading.Thread(target=fuc,args=(arg,))