《Python》进程收尾线程初识
一、數(shù)據(jù)共享
from multiprocessing import Manager
把所有實(shí)現(xiàn)了數(shù)據(jù)共享的比較便捷的類(lèi)都重新又封裝了一遍,并且在原有的multiprocessing基礎(chǔ)上增加了新的機(jī)制list、dict
機(jī)制:支持的數(shù)據(jù)類(lèi)型非常有限
list、dict都不是數(shù)據(jù)安全的,需要自己加鎖來(lái)保證數(shù)據(jù)安全
from multiprocessing import Manager,Process,Lockdef work(d,lock):with lock:d['count'] -= 1if __name__ == '__main__':lock = Lock()with Manager() as m: # m = Manager()dic = m.dict({'count':100})p_lst = []for i in range(10):p = Process(target=work, args=(dic, lock))p_lst.append(p)p.start()for p in p_lst:p.join()print(dic) #{'count': 90} with ......一大段語(yǔ)句 dis模塊 python的上下文管理 在執(zhí)行一大段語(yǔ)句之前,自動(dòng)做某個(gè)操作 open 在執(zhí)行一大段語(yǔ)句之后,自動(dòng)做某個(gè)操作 close面向?qū)ο蟮哪g(shù)方法(雙下杠杠方法) # 回調(diào)函數(shù) in Poolimport os from multiprocessing import Pooldef func(i):print('第一個(gè)任務(wù)', os.getpid())return '*'*idef call_back(res): #回調(diào)函數(shù)print('回調(diào)函數(shù):', os.getpid())print('res--->', res)if __name__ == '__main__':p = Pool()print('主進(jìn)程', os.getpid())p.apply_async(func, args=(1,), callback=call_back)p.close()p.join()func執(zhí)行完畢之后執(zhí)行callback函數(shù)
func的返回值會(huì)作為callback的參數(shù)
回調(diào)函數(shù)是在主進(jìn)程中實(shí)現(xiàn)的
應(yīng)用場(chǎng)景:子進(jìn)程有大量運(yùn)算要做,回調(diào)函數(shù)等待結(jié)果做簡(jiǎn)單處理
import re from urllib.request import urlopen from multiprocessing import Poolurl_lst = ['http://www.baidu.com','http://www.sohu.com','http://www.sogou.com','http://www.4399.com','http://www.cnblogs.com', ]def get_url(url):response = urlopen(url)ret = re.search('www\.(.*?)\.com', url)print('%s finished' % ret.group(1))return ret.group(1),response.read()def call(content):url,con = contentwith open(url+'.html', 'wb')as f:f.write(con) if __name__ == '__main__':p = Pool()for url in url_lst:p.apply_async(get_url,args=(url,),callback=call)p.close()p.join() 子進(jìn)程去訪問(wèn)網(wǎng)頁(yè),主進(jìn)程處理網(wǎng)頁(yè)的結(jié)果?
二、線程理論基礎(chǔ)
進(jìn)程是計(jì)算機(jī)中最小的資源分配單位,進(jìn)程對(duì)于操作系統(tǒng)來(lái)說(shuō)還具有一定的負(fù)擔(dān)
創(chuàng)建一個(gè)進(jìn)程,操作系統(tǒng)分配的資源大約有:代碼,數(shù)據(jù),文件等
1、為什么要有線程
線程是輕量級(jí)的概念,他沒(méi)有屬于自己的進(jìn)程資源,一條線程只負(fù)責(zé)執(zhí)行代碼,沒(méi)有自己獨(dú)立的代碼、數(shù)據(jù)以及文件
線程是計(jì)算機(jī)中能被CPU調(diào)用的最小的單位,當(dāng)前大部分計(jì)算機(jī)中的CPU都是執(zhí)行的線程中的代碼
線程與進(jìn)程之間的關(guān)系:每一個(gè)進(jìn)程中都至少有一條線程在工作
線程的特點(diǎn):
同一個(gè)進(jìn)程中的所有線程的資源是共享的
輕量級(jí), 沒(méi)有自己的資源
進(jìn)程與線程之間的區(qū)別:
占用的資源、調(diào)度的效率、資源是否共享
線程的并行問(wèn)題:
線程可以并行:java、c++,c#等
在cpython中,一個(gè)進(jìn)程中的多個(gè)線程是不可以并行的
原因是:Cpython解釋器內(nèi)部有一把全局解釋器鎖GIL,所以線程不能充分利用多核,同一時(shí)刻同一進(jìn)程中的線程只有一個(gè)能被cpu執(zhí)行
GIL鎖確實(shí)是限制了你程序的效率,但目前可以幫助你提高線程之間切換的效率
如果是想寫(xiě)高計(jì)算型的就要多進(jìn)程或者換一個(gè)解釋器
2、threading 模塊
# 并發(fā)import os from threading import Threaddef func(i):print('子線程:', i, os.getpid())print('主線程', os.getpid()) for i in range(10):t = Thread(target=func, args=(i,))t.start() # 進(jìn)程和線程的差距import os import time from threading import Thread from multiprocessing import Processdef func(i):print('子:', os.getpid())if __name__ == '__main__':start = time.time()t_lst = []for i in range(100):t = Thread(target=func, args=(i,))t.start()t_lst.append(t)for t in t_lst:t.join()end = time.time()-startstart = time.time()t_lst = []for i in range(100):p = Process(target=func, args=(i,))p.start()t_lst.append(p)for p in t_lst:p.join()end2 = time.time()-startprint(end, end2) #0.0279843807220459 13.582834720611572 # 線程間的數(shù)據(jù)共享from threading import Threadnum = 100 def func():global numnum -= 1 #每個(gè)線程都-1 t_lst = [] for i in range(100):t = Thread(target=func) #創(chuàng)建一百個(gè)線程 t.start()t_lst.append(t) for t in t_lst:t.join() print(num) #0?Thread 類(lèi)的其他用法
Thread實(shí)例對(duì)象的方法# isAlive(): 返回線程是否活動(dòng)的。# getName(): 返回線程名。# setName(): 設(shè)置線程名。 threading模塊提供的一些方法:# threading.currentThread(): 返回當(dāng)前的線程變量。# threading.enumerate(): 返回一個(gè)包含正在運(yùn)行的線程的list。正在運(yùn)行指線程啟動(dòng)后、結(jié)束前,不包括啟動(dòng)前和終止后的線程。# threading.activeCount(): 返回正在運(yùn)行的線程數(shù)量,與len(threading.enumerate())有相同的結(jié)果。 from threading import currentThread,Thread def func():time.sleep(2)t = Thread(target=func) t.start() print(t.is_alive()) #True(判斷線程是否活著) print(t.getName()) #Tread-1 t.setName('tt') print(t.getName()) #tt(改名字)def func():print('子線程:', currentThread().ident)time.sleep(2) print('主線程:',currentThread().ident) t = Thread(target=func) t.start() #currentThread().ident返回線程的pidfrom threading import enumerate def func():print('子進(jìn)程:', currentThread().ident)time.sleep(2)print('主進(jìn)程:', currentThread().ident) for i in range(10):t = Thread(target=func)t.start() print(len(enumerate())) #enumerate()返回一個(gè)包含正在運(yùn)行的線程的list,len(list)from threading import activeCount def func():print('子線程:', currentThread().ident)time.sleep(2)print('主線程:', currentThread().ident) for i in range(10):t = Thread(target=func)t.start() print(activeCount()) #activeCount()返回正在運(yùn)行的線程數(shù)量,與len(threading.enumerate())有相同的結(jié)果 示例3、守護(hù)線程
import time from threading import Threaddef func():while True:time.sleep(1)print(123)def func2():print('func2 start')time.sleep(3)print('func2 end')t1 = Thread(target=func) t2 = Thread(target=func2) t1.setDaemon(True) t1.start() t2.start() print('主線程代碼結(jié)束') # func2 start #主線程代碼結(jié)束 #123 #123 #func2 end?
守護(hù)線程 是在主線程代碼結(jié)束之后,再等待子線程執(zhí)行結(jié)束后才結(jié)束
主線程結(jié)束? 就意味著主進(jìn)程結(jié)束
主線程等待所有的線程結(jié)束
主線程結(jié)束了以后? 守護(hù)線程會(huì)隨著主進(jìn)程的結(jié)束而隨之結(jié)束? 不是隨著代碼的結(jié)束而結(jié)束
??
#################################################################################
線程線程和進(jìn)程之間的關(guān)系
每個(gè)進(jìn)程內(nèi)都有一個(gè)線程
線程是不能獨(dú)立存在的
線程和進(jìn)程之間的區(qū)別
同一個(gè)進(jìn)程中線程之間的數(shù)據(jù)是共享的
進(jìn)程之間的數(shù)據(jù)是隔離的
線程是被cpu執(zhí)行的最小單位
操作系統(tǒng)調(diào)度
進(jìn)程是計(jì)算機(jī)中最小的資源分配單位
python
GIL鎖 全局解釋器鎖 全局鎖
cpython解釋器中的
鎖線程 :同一時(shí)刻同一個(gè)進(jìn)程只會(huì)有一個(gè)線程訪問(wèn)CPU
鎖的是線程而不是數(shù)據(jù)
當(dāng)程序是高IO型的 多線程
當(dāng)程序是高計(jì)算(CPU)型的 多進(jìn)程
cpu*1 ~ cpu*2
threading
Thread
守護(hù)線程 :主線程結(jié)束之后才結(jié)束
socket_server IO多路復(fù)用 + 多線程
框架 并發(fā)的效果 :多線程、協(xié)程的概念 flask
爬蟲(chóng) :線程池 協(xié)程
set、dict、list
生成器
面向?qū)ο蟮倪M(jìn)階 :魔術(shù)方法
管道
socket_server的源碼
轉(zhuǎn)載于:https://www.cnblogs.com/yzh2857/p/9699875.html
總結(jié)
以上是生活随笔為你收集整理的《Python》进程收尾线程初识的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: dedecms ---m站功能基础详解
- 下一篇: 湖北省黄冈市黄梅县龙感湖怎么样?